diff options
| -rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt | 19 | ||||
| -rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt | 15 | ||||
| -rw-r--r-- | src/android/app/src/main/jni/android_common/android_common.cpp | 16 | ||||
| -rw-r--r-- | src/android/app/src/main/jni/android_common/android_common.h | 7 | ||||
| -rw-r--r-- | src/android/app/src/main/jni/id_cache.cpp | 46 | ||||
| -rw-r--r-- | src/android/app/src/main/jni/id_cache.h | 8 | ||||
| -rw-r--r-- | src/android/app/src/main/jni/native.cpp | 80 | ||||
| -rw-r--r-- | src/android/app/src/main/jni/native.h | 2 | ||||
| -rw-r--r-- | src/frontend_common/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/frontend_common/content_manager.h | 168 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 166 | ||||
| -rw-r--r-- | src/yuzu/main.h | 11 |
12 files changed, 318 insertions, 221 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt index b7556e353..8cb98d6d7 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt | |||
| @@ -21,6 +21,7 @@ import org.yuzu.yuzu_emu.utils.DocumentsTree | |||
| 21 | import org.yuzu.yuzu_emu.utils.FileUtil | 21 | import org.yuzu.yuzu_emu.utils.FileUtil |
| 22 | import org.yuzu.yuzu_emu.utils.Log | 22 | import org.yuzu.yuzu_emu.utils.Log |
| 23 | import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable | 23 | import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable |
| 24 | import org.yuzu.yuzu_emu.model.InstallResult | ||
| 24 | 25 | ||
| 25 | /** | 26 | /** |
| 26 | * Class which contains methods that interact | 27 | * Class which contains methods that interact |
| @@ -235,9 +236,12 @@ object NativeLibrary { | |||
| 235 | /** | 236 | /** |
| 236 | * Installs a nsp or xci file to nand | 237 | * Installs a nsp or xci file to nand |
| 237 | * @param filename String representation of file uri | 238 | * @param filename String representation of file uri |
| 238 | * @param extension Lowercase string representation of file extension without "." | 239 | * @return int representation of [InstallResult] |
| 239 | */ | 240 | */ |
| 240 | external fun installFileToNand(filename: String, extension: String): Int | 241 | external fun installFileToNand( |
| 242 | filename: String, | ||
| 243 | callback: (max: Long, progress: Long) -> Boolean | ||
| 244 | ): Int | ||
| 241 | 245 | ||
| 242 | external fun doesUpdateMatchProgram(programId: String, updatePath: String): Boolean | 246 | external fun doesUpdateMatchProgram(programId: String, updatePath: String): Boolean |
| 243 | 247 | ||
| @@ -609,15 +613,4 @@ object NativeLibrary { | |||
| 609 | const val RELEASED = 0 | 613 | const val RELEASED = 0 |
| 610 | const val PRESSED = 1 | 614 | const val PRESSED = 1 |
| 611 | } | 615 | } |
| 612 | |||
| 613 | /** | ||
| 614 | * Result from installFileToNand | ||
| 615 | */ | ||
| 616 | object InstallFileToNandResult { | ||
| 617 | const val Success = 0 | ||
| 618 | const val SuccessFileOverwritten = 1 | ||
| 619 | const val Error = 2 | ||
| 620 | const val ErrorBaseGame = 3 | ||
| 621 | const val ErrorFilenameExtension = 4 | ||
| 622 | } | ||
| 623 | } | 616 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt new file mode 100644 index 000000000..0c3cd0521 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.model | ||
| 5 | |||
| 6 | enum class InstallResult(val int: Int) { | ||
| 7 | Success(0), | ||
| 8 | Overwrite(1), | ||
| 9 | Failure(2), | ||
| 10 | BaseInstallAttempted(3); | ||
| 11 | |||
| 12 | companion object { | ||
| 13 | fun from(int: Int): InstallResult = entries.firstOrNull { it.int == int } ?: Success | ||
| 14 | } | ||
| 15 | } | ||
diff --git a/src/android/app/src/main/jni/android_common/android_common.cpp b/src/android/app/src/main/jni/android_common/android_common.cpp index 1e884ffdd..7018a52af 100644 --- a/src/android/app/src/main/jni/android_common/android_common.cpp +++ b/src/android/app/src/main/jni/android_common/android_common.cpp | |||
| @@ -42,3 +42,19 @@ double GetJDouble(JNIEnv* env, jobject jdouble) { | |||
| 42 | jobject ToJDouble(JNIEnv* env, double value) { | 42 | jobject ToJDouble(JNIEnv* env, double value) { |
| 43 | return env->NewObject(IDCache::GetDoubleClass(), IDCache::GetDoubleConstructor(), value); | 43 | return env->NewObject(IDCache::GetDoubleClass(), IDCache::GetDoubleConstructor(), value); |
| 44 | } | 44 | } |
| 45 | |||
| 46 | s32 GetJInteger(JNIEnv* env, jobject jinteger) { | ||
| 47 | return env->GetIntField(jinteger, IDCache::GetIntegerValueField()); | ||
| 48 | } | ||
| 49 | |||
| 50 | jobject ToJInteger(JNIEnv* env, s32 value) { | ||
| 51 | return env->NewObject(IDCache::GetIntegerClass(), IDCache::GetIntegerConstructor(), value); | ||
| 52 | } | ||
| 53 | |||
| 54 | bool GetJBoolean(JNIEnv* env, jobject jboolean) { | ||
| 55 | return env->GetBooleanField(jboolean, IDCache::GetBooleanValueField()); | ||
| 56 | } | ||
| 57 | |||
| 58 | jobject ToJBoolean(JNIEnv* env, bool value) { | ||
| 59 | return env->NewObject(IDCache::GetBooleanClass(), IDCache::GetBooleanConstructor(), value); | ||
| 60 | } | ||
diff --git a/src/android/app/src/main/jni/android_common/android_common.h b/src/android/app/src/main/jni/android_common/android_common.h index 8eb803e1b..29a338c0a 100644 --- a/src/android/app/src/main/jni/android_common/android_common.h +++ b/src/android/app/src/main/jni/android_common/android_common.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <string> | 6 | #include <string> |
| 7 | 7 | ||
| 8 | #include <jni.h> | 8 | #include <jni.h> |
| 9 | #include "common/common_types.h" | ||
| 9 | 10 | ||
| 10 | std::string GetJString(JNIEnv* env, jstring jstr); | 11 | std::string GetJString(JNIEnv* env, jstring jstr); |
| 11 | jstring ToJString(JNIEnv* env, std::string_view str); | 12 | jstring ToJString(JNIEnv* env, std::string_view str); |
| @@ -13,3 +14,9 @@ jstring ToJString(JNIEnv* env, std::u16string_view str); | |||
| 13 | 14 | ||
| 14 | double GetJDouble(JNIEnv* env, jobject jdouble); | 15 | double GetJDouble(JNIEnv* env, jobject jdouble); |
| 15 | jobject ToJDouble(JNIEnv* env, double value); | 16 | jobject ToJDouble(JNIEnv* env, double value); |
| 17 | |||
| 18 | s32 GetJInteger(JNIEnv* env, jobject jinteger); | ||
| 19 | jobject ToJInteger(JNIEnv* env, s32 value); | ||
| 20 | |||
| 21 | bool GetJBoolean(JNIEnv* env, jobject jboolean); | ||
| 22 | jobject ToJBoolean(JNIEnv* env, bool value); | ||
diff --git a/src/android/app/src/main/jni/id_cache.cpp b/src/android/app/src/main/jni/id_cache.cpp index c79ad7d76..19ced175f 100644 --- a/src/android/app/src/main/jni/id_cache.cpp +++ b/src/android/app/src/main/jni/id_cache.cpp | |||
| @@ -47,6 +47,14 @@ static jclass s_double_class; | |||
| 47 | static jmethodID s_double_constructor; | 47 | static jmethodID s_double_constructor; |
| 48 | static jfieldID s_double_value_field; | 48 | static jfieldID s_double_value_field; |
| 49 | 49 | ||
| 50 | static jclass s_integer_class; | ||
| 51 | static jmethodID s_integer_constructor; | ||
| 52 | static jfieldID s_integer_value_field; | ||
| 53 | |||
| 54 | static jclass s_boolean_class; | ||
| 55 | static jmethodID s_boolean_constructor; | ||
| 56 | static jfieldID s_boolean_value_field; | ||
| 57 | |||
| 50 | static constexpr jint JNI_VERSION = JNI_VERSION_1_6; | 58 | static constexpr jint JNI_VERSION = JNI_VERSION_1_6; |
| 51 | 59 | ||
| 52 | namespace IDCache { | 60 | namespace IDCache { |
| @@ -198,6 +206,30 @@ jfieldID GetDoubleValueField() { | |||
| 198 | return s_double_value_field; | 206 | return s_double_value_field; |
| 199 | } | 207 | } |
| 200 | 208 | ||
| 209 | jclass GetIntegerClass() { | ||
| 210 | return s_integer_class; | ||
| 211 | } | ||
| 212 | |||
| 213 | jmethodID GetIntegerConstructor() { | ||
| 214 | return s_integer_constructor; | ||
| 215 | } | ||
| 216 | |||
| 217 | jfieldID GetIntegerValueField() { | ||
| 218 | return s_integer_value_field; | ||
| 219 | } | ||
| 220 | |||
| 221 | jclass GetBooleanClass() { | ||
| 222 | return s_boolean_class; | ||
| 223 | } | ||
| 224 | |||
| 225 | jmethodID GetBooleanConstructor() { | ||
| 226 | return s_boolean_constructor; | ||
| 227 | } | ||
| 228 | |||
| 229 | jfieldID GetBooleanValueField() { | ||
| 230 | return s_boolean_value_field; | ||
| 231 | } | ||
| 232 | |||
| 201 | } // namespace IDCache | 233 | } // namespace IDCache |
| 202 | 234 | ||
| 203 | #ifdef __cplusplus | 235 | #ifdef __cplusplus |
| @@ -284,6 +316,18 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { | |||
| 284 | s_double_value_field = env->GetFieldID(double_class, "value", "D"); | 316 | s_double_value_field = env->GetFieldID(double_class, "value", "D"); |
| 285 | env->DeleteLocalRef(double_class); | 317 | env->DeleteLocalRef(double_class); |
| 286 | 318 | ||
| 319 | const jclass int_class = env->FindClass("java/lang/Integer"); | ||
| 320 | s_integer_class = reinterpret_cast<jclass>(env->NewGlobalRef(int_class)); | ||
| 321 | s_integer_constructor = env->GetMethodID(int_class, "<init>", "(I)V"); | ||
| 322 | s_integer_value_field = env->GetFieldID(int_class, "value", "I"); | ||
| 323 | env->DeleteLocalRef(int_class); | ||
| 324 | |||
| 325 | const jclass boolean_class = env->FindClass("java/lang/Boolean"); | ||
| 326 | s_boolean_class = reinterpret_cast<jclass>(env->NewGlobalRef(boolean_class)); | ||
| 327 | s_boolean_constructor = env->GetMethodID(boolean_class, "<init>", "(Z)V"); | ||
| 328 | s_boolean_value_field = env->GetFieldID(boolean_class, "value", "Z"); | ||
| 329 | env->DeleteLocalRef(boolean_class); | ||
| 330 | |||
| 287 | // Initialize Android Storage | 331 | // Initialize Android Storage |
| 288 | Common::FS::Android::RegisterCallbacks(env, s_native_library_class); | 332 | Common::FS::Android::RegisterCallbacks(env, s_native_library_class); |
| 289 | 333 | ||
| @@ -310,6 +354,8 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) { | |||
| 310 | env->DeleteGlobalRef(s_pair_class); | 354 | env->DeleteGlobalRef(s_pair_class); |
| 311 | env->DeleteGlobalRef(s_overlay_control_data_class); | 355 | env->DeleteGlobalRef(s_overlay_control_data_class); |
| 312 | env->DeleteGlobalRef(s_double_class); | 356 | env->DeleteGlobalRef(s_double_class); |
| 357 | env->DeleteGlobalRef(s_integer_class); | ||
| 358 | env->DeleteGlobalRef(s_boolean_class); | ||
| 313 | 359 | ||
| 314 | // UnInitialize applets | 360 | // UnInitialize applets |
| 315 | SoftwareKeyboard::CleanupJNI(env); | 361 | SoftwareKeyboard::CleanupJNI(env); |
diff --git a/src/android/app/src/main/jni/id_cache.h b/src/android/app/src/main/jni/id_cache.h index 784d1412f..0e5267b73 100644 --- a/src/android/app/src/main/jni/id_cache.h +++ b/src/android/app/src/main/jni/id_cache.h | |||
| @@ -47,4 +47,12 @@ jclass GetDoubleClass(); | |||
| 47 | jmethodID GetDoubleConstructor(); | 47 | jmethodID GetDoubleConstructor(); |
| 48 | jfieldID GetDoubleValueField(); | 48 | jfieldID GetDoubleValueField(); |
| 49 | 49 | ||
| 50 | jclass GetIntegerClass(); | ||
| 51 | jmethodID GetIntegerConstructor(); | ||
| 52 | jfieldID GetIntegerValueField(); | ||
| 53 | |||
| 54 | jclass GetBooleanClass(); | ||
| 55 | jmethodID GetBooleanConstructor(); | ||
| 56 | jfieldID GetBooleanValueField(); | ||
| 57 | |||
| 50 | } // namespace IDCache | 58 | } // namespace IDCache |
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index ed3b1353a..b8fef5c6f 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <core/file_sys/patch_manager.h> | 17 | #include <core/file_sys/patch_manager.h> |
| 18 | #include <core/file_sys/savedata_factory.h> | 18 | #include <core/file_sys/savedata_factory.h> |
| 19 | #include <core/loader/nro.h> | 19 | #include <core/loader/nro.h> |
| 20 | #include <frontend_common/content_manager.h> | ||
| 20 | #include <jni.h> | 21 | #include <jni.h> |
| 21 | 22 | ||
| 22 | #include "common/detached_tasks.h" | 23 | #include "common/detached_tasks.h" |
| @@ -100,67 +101,6 @@ void EmulationSession::SetNativeWindow(ANativeWindow* native_window) { | |||
| 100 | m_native_window = native_window; | 101 | m_native_window = native_window; |
| 101 | } | 102 | } |
| 102 | 103 | ||
| 103 | int EmulationSession::InstallFileToNand(std::string filename, std::string file_extension) { | ||
| 104 | jconst copy_func = [](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest, | ||
| 105 | std::size_t block_size) { | ||
| 106 | if (src == nullptr || dest == nullptr) { | ||
| 107 | return false; | ||
| 108 | } | ||
| 109 | if (!dest->Resize(src->GetSize())) { | ||
| 110 | return false; | ||
| 111 | } | ||
| 112 | |||
| 113 | using namespace Common::Literals; | ||
| 114 | [[maybe_unused]] std::vector<u8> buffer(1_MiB); | ||
| 115 | |||
| 116 | for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { | ||
| 117 | jconst read = src->Read(buffer.data(), buffer.size(), i); | ||
| 118 | dest->Write(buffer.data(), read, i); | ||
| 119 | } | ||
| 120 | return true; | ||
| 121 | }; | ||
| 122 | |||
| 123 | enum InstallResult { | ||
| 124 | Success = 0, | ||
| 125 | SuccessFileOverwritten = 1, | ||
| 126 | InstallError = 2, | ||
| 127 | ErrorBaseGame = 3, | ||
| 128 | ErrorFilenameExtension = 4, | ||
| 129 | }; | ||
| 130 | |||
| 131 | [[maybe_unused]] std::shared_ptr<FileSys::NSP> nsp; | ||
| 132 | if (file_extension == "nsp") { | ||
| 133 | nsp = std::make_shared<FileSys::NSP>(m_vfs->OpenFile(filename, FileSys::Mode::Read)); | ||
| 134 | if (nsp->IsExtractedType()) { | ||
| 135 | return InstallError; | ||
| 136 | } | ||
| 137 | } else { | ||
| 138 | return ErrorFilenameExtension; | ||
| 139 | } | ||
| 140 | |||
| 141 | if (!nsp) { | ||
| 142 | return InstallError; | ||
| 143 | } | ||
| 144 | |||
| 145 | if (nsp->GetStatus() != Loader::ResultStatus::Success) { | ||
| 146 | return InstallError; | ||
| 147 | } | ||
| 148 | |||
| 149 | jconst res = m_system.GetFileSystemController().GetUserNANDContents()->InstallEntry(*nsp, true, | ||
| 150 | copy_func); | ||
| 151 | |||
| 152 | switch (res) { | ||
| 153 | case FileSys::InstallResult::Success: | ||
| 154 | return Success; | ||
| 155 | case FileSys::InstallResult::OverwriteExisting: | ||
| 156 | return SuccessFileOverwritten; | ||
| 157 | case FileSys::InstallResult::ErrorBaseInstall: | ||
| 158 | return ErrorBaseGame; | ||
| 159 | default: | ||
| 160 | return InstallError; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | void EmulationSession::InitializeGpuDriver(const std::string& hook_lib_dir, | 104 | void EmulationSession::InitializeGpuDriver(const std::string& hook_lib_dir, |
| 165 | const std::string& custom_driver_dir, | 105 | const std::string& custom_driver_dir, |
| 166 | const std::string& custom_driver_name, | 106 | const std::string& custom_driver_name, |
| @@ -512,10 +452,20 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_setAppDirectory(JNIEnv* env, jobject | |||
| 512 | } | 452 | } |
| 513 | 453 | ||
| 514 | int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject instance, | 454 | int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject instance, |
| 515 | jstring j_file, | 455 | jstring j_file, jobject jcallback) { |
| 516 | jstring j_file_extension) { | 456 | auto jlambdaClass = env->GetObjectClass(jcallback); |
| 517 | return EmulationSession::GetInstance().InstallFileToNand(GetJString(env, j_file), | 457 | auto jlambdaInvokeMethod = env->GetMethodID( |
| 518 | GetJString(env, j_file_extension)); | 458 | jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); |
| 459 | const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) { | ||
| 460 | auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod, | ||
| 461 | ToJDouble(env, max), ToJDouble(env, progress)); | ||
| 462 | return GetJBoolean(env, jwasCancelled); | ||
| 463 | }; | ||
| 464 | |||
| 465 | return static_cast<int>( | ||
| 466 | ContentManager::InstallNSP(&EmulationSession::GetInstance().System(), | ||
| 467 | EmulationSession::GetInstance().System().GetFilesystem().get(), | ||
| 468 | GetJString(env, j_file), callback)); | ||
| 519 | } | 469 | } |
| 520 | 470 | ||
| 521 | jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* env, jobject jobj, | 471 | jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* env, jobject jobj, |
diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h index 4a8049578..dadb138ad 100644 --- a/src/android/app/src/main/jni/native.h +++ b/src/android/app/src/main/jni/native.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "core/file_sys/registered_cache.h" | 7 | #include "core/file_sys/registered_cache.h" |
| 8 | #include "core/hle/service/acc/profile_manager.h" | 8 | #include "core/hle/service/acc/profile_manager.h" |
| 9 | #include "core/perf_stats.h" | 9 | #include "core/perf_stats.h" |
| 10 | #include "frontend_common/content_manager.h" | ||
| 10 | #include "jni/applets/software_keyboard.h" | 11 | #include "jni/applets/software_keyboard.h" |
| 11 | #include "jni/emu_window/emu_window.h" | 12 | #include "jni/emu_window/emu_window.h" |
| 12 | #include "video_core/rasterizer_interface.h" | 13 | #include "video_core/rasterizer_interface.h" |
| @@ -29,7 +30,6 @@ public: | |||
| 29 | void SetNativeWindow(ANativeWindow* native_window); | 30 | void SetNativeWindow(ANativeWindow* native_window); |
| 30 | void SurfaceChanged(); | 31 | void SurfaceChanged(); |
| 31 | 32 | ||
| 32 | int InstallFileToNand(std::string filename, std::string file_extension); | ||
| 33 | void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir, | 33 | void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir, |
| 34 | const std::string& custom_driver_name, | 34 | const std::string& custom_driver_name, |
| 35 | const std::string& file_redirect_dir); | 35 | const std::string& file_redirect_dir); |
diff --git a/src/frontend_common/CMakeLists.txt b/src/frontend_common/CMakeLists.txt index 22e9337c4..94d8cc4c3 100644 --- a/src/frontend_common/CMakeLists.txt +++ b/src/frontend_common/CMakeLists.txt | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | add_library(frontend_common STATIC | 4 | add_library(frontend_common STATIC |
| 5 | config.cpp | 5 | config.cpp |
| 6 | config.h | 6 | config.h |
| 7 | content_manager.h | ||
| 7 | ) | 8 | ) |
| 8 | 9 | ||
| 9 | create_target_directory_groups(frontend_common) | 10 | create_target_directory_groups(frontend_common) |
diff --git a/src/frontend_common/content_manager.h b/src/frontend_common/content_manager.h new file mode 100644 index 000000000..8e55f4ca0 --- /dev/null +++ b/src/frontend_common/content_manager.h | |||
| @@ -0,0 +1,168 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <boost/algorithm/string.hpp> | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/literals.h" | ||
| 9 | #include "core/core.h" | ||
| 10 | #include "core/file_sys/common_funcs.h" | ||
| 11 | #include "core/file_sys/content_archive.h" | ||
| 12 | #include "core/file_sys/mode.h" | ||
| 13 | #include "core/file_sys/nca_metadata.h" | ||
| 14 | #include "core/file_sys/registered_cache.h" | ||
| 15 | #include "core/file_sys/submission_package.h" | ||
| 16 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 17 | #include "core/loader/loader.h" | ||
| 18 | |||
| 19 | namespace ContentManager { | ||
| 20 | |||
| 21 | enum class InstallResult { | ||
| 22 | Success, | ||
| 23 | Overwrite, | ||
| 24 | Failure, | ||
| 25 | BaseInstallAttempted, | ||
| 26 | }; | ||
| 27 | |||
| 28 | inline bool RemoveDLC(const Service::FileSystem::FileSystemController& fs_controller, | ||
| 29 | const u64 title_id) { | ||
| 30 | return fs_controller.GetUserNANDContents()->RemoveExistingEntry(title_id) || | ||
| 31 | fs_controller.GetSDMCContents()->RemoveExistingEntry(title_id); | ||
| 32 | } | ||
| 33 | |||
| 34 | inline size_t RemoveAllDLC(Core::System* system, const u64 program_id) { | ||
| 35 | size_t count{}; | ||
| 36 | const auto& fs_controller = system->GetFileSystemController(); | ||
| 37 | const auto dlc_entries = system->GetContentProvider().ListEntriesFilter( | ||
| 38 | FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); | ||
| 39 | std::vector<u64> program_dlc_entries; | ||
| 40 | |||
| 41 | for (const auto& entry : dlc_entries) { | ||
| 42 | if (FileSys::GetBaseTitleID(entry.title_id) == program_id) { | ||
| 43 | program_dlc_entries.push_back(entry.title_id); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | for (const auto& entry : program_dlc_entries) { | ||
| 48 | if (RemoveDLC(fs_controller, entry)) { | ||
| 49 | ++count; | ||
| 50 | } | ||
| 51 | } | ||
| 52 | return count; | ||
| 53 | } | ||
| 54 | |||
| 55 | inline bool RemoveUpdate(const Service::FileSystem::FileSystemController& fs_controller, | ||
| 56 | const u64 program_id) { | ||
| 57 | const auto update_id = program_id | 0x800; | ||
| 58 | return fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) || | ||
| 59 | fs_controller.GetSDMCContents()->RemoveExistingEntry(update_id); | ||
| 60 | } | ||
| 61 | |||
| 62 | inline bool RemoveBaseContent(const Service::FileSystem::FileSystemController& fs_controller, | ||
| 63 | const u64 program_id) { | ||
| 64 | return fs_controller.GetUserNANDContents()->RemoveExistingEntry(program_id) || | ||
| 65 | fs_controller.GetSDMCContents()->RemoveExistingEntry(program_id); | ||
| 66 | } | ||
| 67 | |||
| 68 | inline InstallResult InstallNSP( | ||
| 69 | Core::System* system, FileSys::VfsFilesystem* vfs, const std::string& filename, | ||
| 70 | const std::function<bool(size_t, size_t)>& callback = std::function<bool(size_t, size_t)>()) { | ||
| 71 | const auto copy = [callback](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest, | ||
| 72 | std::size_t block_size) { | ||
| 73 | if (src == nullptr || dest == nullptr) { | ||
| 74 | return false; | ||
| 75 | } | ||
| 76 | if (!dest->Resize(src->GetSize())) { | ||
| 77 | return false; | ||
| 78 | } | ||
| 79 | |||
| 80 | using namespace Common::Literals; | ||
| 81 | std::vector<u8> buffer(1_MiB); | ||
| 82 | |||
| 83 | for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { | ||
| 84 | if (callback(src->GetSize(), i)) { | ||
| 85 | dest->Resize(0); | ||
| 86 | return false; | ||
| 87 | } | ||
| 88 | const auto read = src->Read(buffer.data(), buffer.size(), i); | ||
| 89 | dest->Write(buffer.data(), read, i); | ||
| 90 | } | ||
| 91 | return true; | ||
| 92 | }; | ||
| 93 | |||
| 94 | std::shared_ptr<FileSys::NSP> nsp; | ||
| 95 | FileSys::VirtualFile file = vfs->OpenFile(filename, FileSys::Mode::Read); | ||
| 96 | if (boost::to_lower_copy(file->GetName()).ends_with(std::string("nsp"))) { | ||
| 97 | nsp = std::make_shared<FileSys::NSP>(file); | ||
| 98 | if (nsp->IsExtractedType()) { | ||
| 99 | return InstallResult::Failure; | ||
| 100 | } | ||
| 101 | } else { | ||
| 102 | return InstallResult::Failure; | ||
| 103 | } | ||
| 104 | |||
| 105 | if (nsp->GetStatus() != Loader::ResultStatus::Success) { | ||
| 106 | return InstallResult::Failure; | ||
| 107 | } | ||
| 108 | const auto res = | ||
| 109 | system->GetFileSystemController().GetUserNANDContents()->InstallEntry(*nsp, true, copy); | ||
| 110 | switch (res) { | ||
| 111 | case FileSys::InstallResult::Success: | ||
| 112 | return InstallResult::Success; | ||
| 113 | case FileSys::InstallResult::OverwriteExisting: | ||
| 114 | return InstallResult::Overwrite; | ||
| 115 | case FileSys::InstallResult::ErrorBaseInstall: | ||
| 116 | return InstallResult::BaseInstallAttempted; | ||
| 117 | default: | ||
| 118 | return InstallResult::Failure; | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | inline InstallResult InstallNCA( | ||
| 123 | FileSys::VfsFilesystem* vfs, const std::string& filename, | ||
| 124 | FileSys::RegisteredCache* registered_cache, const FileSys::TitleType title_type, | ||
| 125 | const std::function<bool(size_t, size_t)>& callback = std::function<bool(size_t, size_t)>()) { | ||
| 126 | const auto copy = [callback](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest, | ||
| 127 | std::size_t block_size) { | ||
| 128 | if (src == nullptr || dest == nullptr) { | ||
| 129 | return false; | ||
| 130 | } | ||
| 131 | if (!dest->Resize(src->GetSize())) { | ||
| 132 | return false; | ||
| 133 | } | ||
| 134 | |||
| 135 | using namespace Common::Literals; | ||
| 136 | std::vector<u8> buffer(1_MiB); | ||
| 137 | |||
| 138 | for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { | ||
| 139 | if (callback(src->GetSize(), i)) { | ||
| 140 | dest->Resize(0); | ||
| 141 | return false; | ||
| 142 | } | ||
| 143 | const auto read = src->Read(buffer.data(), buffer.size(), i); | ||
| 144 | dest->Write(buffer.data(), read, i); | ||
| 145 | } | ||
| 146 | return true; | ||
| 147 | }; | ||
| 148 | |||
| 149 | const auto nca = std::make_shared<FileSys::NCA>(vfs->OpenFile(filename, FileSys::Mode::Read)); | ||
| 150 | const auto id = nca->GetStatus(); | ||
| 151 | |||
| 152 | // Game updates necessary are missing base RomFS | ||
| 153 | if (id != Loader::ResultStatus::Success && | ||
| 154 | id != Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) { | ||
| 155 | return InstallResult::Failure; | ||
| 156 | } | ||
| 157 | |||
| 158 | const auto res = registered_cache->InstallEntry(*nca, title_type, true, copy); | ||
| 159 | if (res == FileSys::InstallResult::Success) { | ||
| 160 | return InstallResult::Success; | ||
| 161 | } else if (res == FileSys::InstallResult::OverwriteExisting) { | ||
| 162 | return InstallResult::Overwrite; | ||
| 163 | } else { | ||
| 164 | return InstallResult::Failure; | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | } // namespace ContentManager | ||
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 3c562e3b2..05bd4174c 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | #include "core/hle/service/am/applet_oe.h" | 47 | #include "core/hle/service/am/applet_oe.h" |
| 48 | #include "core/hle/service/am/applets/applets.h" | 48 | #include "core/hle/service/am/applets/applets.h" |
| 49 | #include "core/hle/service/set/system_settings_server.h" | 49 | #include "core/hle/service/set/system_settings_server.h" |
| 50 | #include "frontend_common/content_manager.h" | ||
| 50 | #include "hid_core/frontend/emulated_controller.h" | 51 | #include "hid_core/frontend/emulated_controller.h" |
| 51 | #include "hid_core/hid_core.h" | 52 | #include "hid_core/hid_core.h" |
| 52 | #include "yuzu/multiplayer/state.h" | 53 | #include "yuzu/multiplayer/state.h" |
| @@ -2476,10 +2477,8 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT | |||
| 2476 | } | 2477 | } |
| 2477 | 2478 | ||
| 2478 | void GMainWindow::RemoveBaseContent(u64 program_id, InstalledEntryType type) { | 2479 | void GMainWindow::RemoveBaseContent(u64 program_id, InstalledEntryType type) { |
| 2479 | const auto& fs_controller = system->GetFileSystemController(); | 2480 | const auto res = |
| 2480 | const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(program_id) || | 2481 | ContentManager::RemoveBaseContent(system->GetFileSystemController(), program_id); |
| 2481 | fs_controller.GetSDMCContents()->RemoveExistingEntry(program_id); | ||
| 2482 | |||
| 2483 | if (res) { | 2482 | if (res) { |
| 2484 | QMessageBox::information(this, tr("Successfully Removed"), | 2483 | QMessageBox::information(this, tr("Successfully Removed"), |
| 2485 | tr("Successfully removed the installed base game.")); | 2484 | tr("Successfully removed the installed base game.")); |
| @@ -2491,11 +2490,7 @@ void GMainWindow::RemoveBaseContent(u64 program_id, InstalledEntryType type) { | |||
| 2491 | } | 2490 | } |
| 2492 | 2491 | ||
| 2493 | void GMainWindow::RemoveUpdateContent(u64 program_id, InstalledEntryType type) { | 2492 | void GMainWindow::RemoveUpdateContent(u64 program_id, InstalledEntryType type) { |
| 2494 | const auto update_id = program_id | 0x800; | 2493 | const auto res = ContentManager::RemoveUpdate(system->GetFileSystemController(), program_id); |
| 2495 | const auto& fs_controller = system->GetFileSystemController(); | ||
| 2496 | const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) || | ||
| 2497 | fs_controller.GetSDMCContents()->RemoveExistingEntry(update_id); | ||
| 2498 | |||
| 2499 | if (res) { | 2494 | if (res) { |
| 2500 | QMessageBox::information(this, tr("Successfully Removed"), | 2495 | QMessageBox::information(this, tr("Successfully Removed"), |
| 2501 | tr("Successfully removed the installed update.")); | 2496 | tr("Successfully removed the installed update.")); |
| @@ -2506,22 +2501,7 @@ void GMainWindow::RemoveUpdateContent(u64 program_id, InstalledEntryType type) { | |||
| 2506 | } | 2501 | } |
| 2507 | 2502 | ||
| 2508 | void GMainWindow::RemoveAddOnContent(u64 program_id, InstalledEntryType type) { | 2503 | void GMainWindow::RemoveAddOnContent(u64 program_id, InstalledEntryType type) { |
| 2509 | u32 count{}; | 2504 | const size_t count = ContentManager::RemoveAllDLC(system.get(), program_id); |
| 2510 | const auto& fs_controller = system->GetFileSystemController(); | ||
| 2511 | const auto dlc_entries = system->GetContentProvider().ListEntriesFilter( | ||
| 2512 | FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); | ||
| 2513 | |||
| 2514 | for (const auto& entry : dlc_entries) { | ||
| 2515 | if (FileSys::GetBaseTitleID(entry.title_id) == program_id) { | ||
| 2516 | const auto res = | ||
| 2517 | fs_controller.GetUserNANDContents()->RemoveExistingEntry(entry.title_id) || | ||
| 2518 | fs_controller.GetSDMCContents()->RemoveExistingEntry(entry.title_id); | ||
| 2519 | if (res) { | ||
| 2520 | ++count; | ||
| 2521 | } | ||
| 2522 | } | ||
| 2523 | } | ||
| 2524 | |||
| 2525 | if (count == 0) { | 2505 | if (count == 0) { |
| 2526 | QMessageBox::warning(this, GetGameListErrorRemoving(type), | 2506 | QMessageBox::warning(this, GetGameListErrorRemoving(type), |
| 2527 | tr("There are no DLC installed for this title.")); | 2507 | tr("There are no DLC installed for this title.")); |
| @@ -3290,12 +3270,21 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 3290 | install_progress->setLabelText( | 3270 | install_progress->setLabelText( |
| 3291 | tr("Installing file \"%1\"...").arg(QFileInfo(file).fileName())); | 3271 | tr("Installing file \"%1\"...").arg(QFileInfo(file).fileName())); |
| 3292 | 3272 | ||
| 3293 | QFuture<InstallResult> future; | 3273 | QFuture<ContentManager::InstallResult> future; |
| 3294 | InstallResult result; | 3274 | ContentManager::InstallResult result; |
| 3295 | 3275 | ||
| 3296 | if (file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { | 3276 | if (file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { |
| 3297 | 3277 | const auto progress_callback = [this](size_t size, size_t progress) { | |
| 3298 | future = QtConcurrent::run([this, &file] { return InstallNSP(file); }); | 3278 | emit UpdateInstallProgress(); |
| 3279 | if (install_progress->wasCanceled()) { | ||
| 3280 | return true; | ||
| 3281 | } | ||
| 3282 | return false; | ||
| 3283 | }; | ||
| 3284 | future = QtConcurrent::run([this, &file, progress_callback] { | ||
| 3285 | return ContentManager::InstallNSP(system.get(), vfs.get(), file.toStdString(), | ||
| 3286 | progress_callback); | ||
| 3287 | }); | ||
| 3299 | 3288 | ||
| 3300 | while (!future.isFinished()) { | 3289 | while (!future.isFinished()) { |
| 3301 | QCoreApplication::processEvents(); | 3290 | QCoreApplication::processEvents(); |
| @@ -3311,16 +3300,16 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 3311 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); | 3300 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); |
| 3312 | 3301 | ||
| 3313 | switch (result) { | 3302 | switch (result) { |
| 3314 | case InstallResult::Success: | 3303 | case ContentManager::InstallResult::Success: |
| 3315 | new_files.append(QFileInfo(file).fileName()); | 3304 | new_files.append(QFileInfo(file).fileName()); |
| 3316 | break; | 3305 | break; |
| 3317 | case InstallResult::Overwrite: | 3306 | case ContentManager::InstallResult::Overwrite: |
| 3318 | overwritten_files.append(QFileInfo(file).fileName()); | 3307 | overwritten_files.append(QFileInfo(file).fileName()); |
| 3319 | break; | 3308 | break; |
| 3320 | case InstallResult::Failure: | 3309 | case ContentManager::InstallResult::Failure: |
| 3321 | failed_files.append(QFileInfo(file).fileName()); | 3310 | failed_files.append(QFileInfo(file).fileName()); |
| 3322 | break; | 3311 | break; |
| 3323 | case InstallResult::BaseInstallAttempted: | 3312 | case ContentManager::InstallResult::BaseInstallAttempted: |
| 3324 | failed_files.append(QFileInfo(file).fileName()); | 3313 | failed_files.append(QFileInfo(file).fileName()); |
| 3325 | detected_base_install = true; | 3314 | detected_base_install = true; |
| 3326 | break; | 3315 | break; |
| @@ -3354,96 +3343,7 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 3354 | ui->action_Install_File_NAND->setEnabled(true); | 3343 | ui->action_Install_File_NAND->setEnabled(true); |
| 3355 | } | 3344 | } |
| 3356 | 3345 | ||
| 3357 | InstallResult GMainWindow::InstallNSP(const QString& filename) { | 3346 | ContentManager::InstallResult GMainWindow::InstallNCA(const QString& filename) { |
| 3358 | const auto qt_raw_copy = [this](const FileSys::VirtualFile& src, | ||
| 3359 | const FileSys::VirtualFile& dest, std::size_t block_size) { | ||
| 3360 | if (src == nullptr || dest == nullptr) { | ||
| 3361 | return false; | ||
| 3362 | } | ||
| 3363 | if (!dest->Resize(src->GetSize())) { | ||
| 3364 | return false; | ||
| 3365 | } | ||
| 3366 | |||
| 3367 | std::vector<u8> buffer(CopyBufferSize); | ||
| 3368 | |||
| 3369 | for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { | ||
| 3370 | if (install_progress->wasCanceled()) { | ||
| 3371 | dest->Resize(0); | ||
| 3372 | return false; | ||
| 3373 | } | ||
| 3374 | |||
| 3375 | emit UpdateInstallProgress(); | ||
| 3376 | |||
| 3377 | const auto read = src->Read(buffer.data(), buffer.size(), i); | ||
| 3378 | dest->Write(buffer.data(), read, i); | ||
| 3379 | } | ||
| 3380 | return true; | ||
| 3381 | }; | ||
| 3382 | |||
| 3383 | std::shared_ptr<FileSys::NSP> nsp; | ||
| 3384 | if (filename.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { | ||
| 3385 | nsp = std::make_shared<FileSys::NSP>( | ||
| 3386 | vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); | ||
| 3387 | if (nsp->IsExtractedType()) { | ||
| 3388 | return InstallResult::Failure; | ||
| 3389 | } | ||
| 3390 | } else { | ||
| 3391 | return InstallResult::Failure; | ||
| 3392 | } | ||
| 3393 | |||
| 3394 | if (nsp->GetStatus() != Loader::ResultStatus::Success) { | ||
| 3395 | return InstallResult::Failure; | ||
| 3396 | } | ||
| 3397 | const auto res = system->GetFileSystemController().GetUserNANDContents()->InstallEntry( | ||
| 3398 | *nsp, true, qt_raw_copy); | ||
| 3399 | switch (res) { | ||
| 3400 | case FileSys::InstallResult::Success: | ||
| 3401 | return InstallResult::Success; | ||
| 3402 | case FileSys::InstallResult::OverwriteExisting: | ||
| 3403 | return InstallResult::Overwrite; | ||
| 3404 | case FileSys::InstallResult::ErrorBaseInstall: | ||
| 3405 | return InstallResult::BaseInstallAttempted; | ||
| 3406 | default: | ||
| 3407 | return InstallResult::Failure; | ||
| 3408 | } | ||
| 3409 | } | ||
| 3410 | |||
| 3411 | InstallResult GMainWindow::InstallNCA(const QString& filename) { | ||
| 3412 | const auto qt_raw_copy = [this](const FileSys::VirtualFile& src, | ||
| 3413 | const FileSys::VirtualFile& dest, std::size_t block_size) { | ||
| 3414 | if (src == nullptr || dest == nullptr) { | ||
| 3415 | return false; | ||
| 3416 | } | ||
| 3417 | if (!dest->Resize(src->GetSize())) { | ||
| 3418 | return false; | ||
| 3419 | } | ||
| 3420 | |||
| 3421 | std::vector<u8> buffer(CopyBufferSize); | ||
| 3422 | |||
| 3423 | for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { | ||
| 3424 | if (install_progress->wasCanceled()) { | ||
| 3425 | dest->Resize(0); | ||
| 3426 | return false; | ||
| 3427 | } | ||
| 3428 | |||
| 3429 | emit UpdateInstallProgress(); | ||
| 3430 | |||
| 3431 | const auto read = src->Read(buffer.data(), buffer.size(), i); | ||
| 3432 | dest->Write(buffer.data(), read, i); | ||
| 3433 | } | ||
| 3434 | return true; | ||
| 3435 | }; | ||
| 3436 | |||
| 3437 | const auto nca = | ||
| 3438 | std::make_shared<FileSys::NCA>(vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); | ||
| 3439 | const auto id = nca->GetStatus(); | ||
| 3440 | |||
| 3441 | // Game updates necessary are missing base RomFS | ||
| 3442 | if (id != Loader::ResultStatus::Success && | ||
| 3443 | id != Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) { | ||
| 3444 | return InstallResult::Failure; | ||
| 3445 | } | ||
| 3446 | |||
| 3447 | const QStringList tt_options{tr("System Application"), | 3347 | const QStringList tt_options{tr("System Application"), |
| 3448 | tr("System Archive"), | 3348 | tr("System Archive"), |
| 3449 | tr("System Application Update"), | 3349 | tr("System Application Update"), |
| @@ -3464,7 +3364,7 @@ InstallResult GMainWindow::InstallNCA(const QString& filename) { | |||
| 3464 | if (!ok || index == -1) { | 3364 | if (!ok || index == -1) { |
| 3465 | QMessageBox::warning(this, tr("Failed to Install"), | 3365 | QMessageBox::warning(this, tr("Failed to Install"), |
| 3466 | tr("The title type you selected for the NCA is invalid.")); | 3366 | tr("The title type you selected for the NCA is invalid.")); |
| 3467 | return InstallResult::Failure; | 3367 | return ContentManager::InstallResult::Failure; |
| 3468 | } | 3368 | } |
| 3469 | 3369 | ||
| 3470 | // If index is equal to or past Game, add the jump in TitleType. | 3370 | // If index is equal to or past Game, add the jump in TitleType. |
| @@ -3478,15 +3378,15 @@ InstallResult GMainWindow::InstallNCA(const QString& filename) { | |||
| 3478 | auto* registered_cache = is_application ? fs_controller.GetUserNANDContents() | 3378 | auto* registered_cache = is_application ? fs_controller.GetUserNANDContents() |
| 3479 | : fs_controller.GetSystemNANDContents(); | 3379 | : fs_controller.GetSystemNANDContents(); |
| 3480 | 3380 | ||
| 3481 | const auto res = registered_cache->InstallEntry(*nca, static_cast<FileSys::TitleType>(index), | 3381 | const auto progress_callback = [this](size_t size, size_t progress) { |
| 3482 | true, qt_raw_copy); | 3382 | emit UpdateInstallProgress(); |
| 3483 | if (res == FileSys::InstallResult::Success) { | 3383 | if (install_progress->wasCanceled()) { |
| 3484 | return InstallResult::Success; | 3384 | return true; |
| 3485 | } else if (res == FileSys::InstallResult::OverwriteExisting) { | 3385 | } |
| 3486 | return InstallResult::Overwrite; | 3386 | return false; |
| 3487 | } else { | 3387 | }; |
| 3488 | return InstallResult::Failure; | 3388 | return ContentManager::InstallNCA(vfs.get(), filename.toStdString(), registered_cache, |
| 3489 | } | 3389 | static_cast<FileSys::TitleType>(index), progress_callback); |
| 3490 | } | 3390 | } |
| 3491 | 3391 | ||
| 3492 | void GMainWindow::OnMenuRecentFile() { | 3392 | void GMainWindow::OnMenuRecentFile() { |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index f3276da64..280fae5c3 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include "common/announce_multiplayer_room.h" | 16 | #include "common/announce_multiplayer_room.h" |
| 17 | #include "common/common_types.h" | 17 | #include "common/common_types.h" |
| 18 | #include "configuration/qt_config.h" | 18 | #include "configuration/qt_config.h" |
| 19 | #include "frontend_common/content_manager.h" | ||
| 19 | #include "input_common/drivers/tas_input.h" | 20 | #include "input_common/drivers/tas_input.h" |
| 20 | #include "yuzu/compatibility_list.h" | 21 | #include "yuzu/compatibility_list.h" |
| 21 | #include "yuzu/hotkeys.h" | 22 | #include "yuzu/hotkeys.h" |
| @@ -124,13 +125,6 @@ enum class EmulatedDirectoryTarget { | |||
| 124 | SDMC, | 125 | SDMC, |
| 125 | }; | 126 | }; |
| 126 | 127 | ||
| 127 | enum class InstallResult { | ||
| 128 | Success, | ||
| 129 | Overwrite, | ||
| 130 | Failure, | ||
| 131 | BaseInstallAttempted, | ||
| 132 | }; | ||
| 133 | |||
| 134 | enum class ReinitializeKeyBehavior { | 128 | enum class ReinitializeKeyBehavior { |
| 135 | NoWarning, | 129 | NoWarning, |
| 136 | Warning, | 130 | Warning, |
| @@ -427,8 +421,7 @@ private: | |||
| 427 | void RemoveCacheStorage(u64 program_id); | 421 | void RemoveCacheStorage(u64 program_id); |
| 428 | bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id, | 422 | bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id, |
| 429 | u64* selected_title_id, u8* selected_content_record_type); | 423 | u64* selected_title_id, u8* selected_content_record_type); |
| 430 | InstallResult InstallNSP(const QString& filename); | 424 | ContentManager::InstallResult InstallNCA(const QString& filename); |
| 431 | InstallResult InstallNCA(const QString& filename); | ||
| 432 | void MigrateConfigFiles(); | 425 | void MigrateConfigFiles(); |
| 433 | void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {}, | 426 | void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {}, |
| 434 | std::string_view gpu_vendor = {}); | 427 | std::string_view gpu_vendor = {}); |