diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt | 29 | ||||
| -rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt | 17 | ||||
| -rw-r--r-- | src/android/app/src/main/jni/native.h | 8 | ||||
| -rw-r--r-- | src/common/fs/fs_android.cpp | 33 | ||||
| -rw-r--r-- | src/common/fs/fs_android.h | 15 | ||||
| -rw-r--r-- | src/common/fs/path_util.cpp | 10 | ||||
| -rw-r--r-- | src/common/string_util.cpp | 12 |
7 files changed, 115 insertions, 9 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 22c9b05de..5fe235dba 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 | |||
| @@ -5,6 +5,7 @@ package org.yuzu.yuzu_emu | |||
| 5 | 5 | ||
| 6 | import android.app.Dialog | 6 | import android.app.Dialog |
| 7 | import android.content.DialogInterface | 7 | import android.content.DialogInterface |
| 8 | import android.net.Uri | ||
| 8 | import android.os.Bundle | 9 | import android.os.Bundle |
| 9 | import android.text.Html | 10 | import android.text.Html |
| 10 | import android.text.method.LinkMovementMethod | 11 | import android.text.method.LinkMovementMethod |
| @@ -16,7 +17,7 @@ import androidx.fragment.app.DialogFragment | |||
| 16 | import com.google.android.material.dialog.MaterialAlertDialogBuilder | 17 | import com.google.android.material.dialog.MaterialAlertDialogBuilder |
| 17 | import java.lang.ref.WeakReference | 18 | import java.lang.ref.WeakReference |
| 18 | import org.yuzu.yuzu_emu.activities.EmulationActivity | 19 | import org.yuzu.yuzu_emu.activities.EmulationActivity |
| 19 | import org.yuzu.yuzu_emu.utils.DocumentsTree.Companion.isNativePath | 20 | import org.yuzu.yuzu_emu.utils.DocumentsTree |
| 20 | import org.yuzu.yuzu_emu.utils.FileUtil | 21 | import org.yuzu.yuzu_emu.utils.FileUtil |
| 21 | import org.yuzu.yuzu_emu.utils.Log | 22 | import org.yuzu.yuzu_emu.utils.Log |
| 22 | import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable | 23 | import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable |
| @@ -68,7 +69,7 @@ object NativeLibrary { | |||
| 68 | @Keep | 69 | @Keep |
| 69 | @JvmStatic | 70 | @JvmStatic |
| 70 | fun openContentUri(path: String?, openmode: String?): Int { | 71 | fun openContentUri(path: String?, openmode: String?): Int { |
| 71 | return if (isNativePath(path!!)) { | 72 | return if (DocumentsTree.isNativePath(path!!)) { |
| 72 | YuzuApplication.documentsTree!!.openContentUri(path, openmode) | 73 | YuzuApplication.documentsTree!!.openContentUri(path, openmode) |
| 73 | } else { | 74 | } else { |
| 74 | FileUtil.openContentUri(path, openmode) | 75 | FileUtil.openContentUri(path, openmode) |
| @@ -78,7 +79,7 @@ object NativeLibrary { | |||
| 78 | @Keep | 79 | @Keep |
| 79 | @JvmStatic | 80 | @JvmStatic |
| 80 | fun getSize(path: String?): Long { | 81 | fun getSize(path: String?): Long { |
| 81 | return if (isNativePath(path!!)) { | 82 | return if (DocumentsTree.isNativePath(path!!)) { |
| 82 | YuzuApplication.documentsTree!!.getFileSize(path) | 83 | YuzuApplication.documentsTree!!.getFileSize(path) |
| 83 | } else { | 84 | } else { |
| 84 | FileUtil.getFileSize(path) | 85 | FileUtil.getFileSize(path) |
| @@ -88,7 +89,7 @@ object NativeLibrary { | |||
| 88 | @Keep | 89 | @Keep |
| 89 | @JvmStatic | 90 | @JvmStatic |
| 90 | fun exists(path: String?): Boolean { | 91 | fun exists(path: String?): Boolean { |
| 91 | return if (isNativePath(path!!)) { | 92 | return if (DocumentsTree.isNativePath(path!!)) { |
| 92 | YuzuApplication.documentsTree!!.exists(path) | 93 | YuzuApplication.documentsTree!!.exists(path) |
| 93 | } else { | 94 | } else { |
| 94 | FileUtil.exists(path) | 95 | FileUtil.exists(path) |
| @@ -98,13 +99,31 @@ object NativeLibrary { | |||
| 98 | @Keep | 99 | @Keep |
| 99 | @JvmStatic | 100 | @JvmStatic |
| 100 | fun isDirectory(path: String?): Boolean { | 101 | fun isDirectory(path: String?): Boolean { |
| 101 | return if (isNativePath(path!!)) { | 102 | return if (DocumentsTree.isNativePath(path!!)) { |
| 102 | YuzuApplication.documentsTree!!.isDirectory(path) | 103 | YuzuApplication.documentsTree!!.isDirectory(path) |
| 103 | } else { | 104 | } else { |
| 104 | FileUtil.isDirectory(path) | 105 | FileUtil.isDirectory(path) |
| 105 | } | 106 | } |
| 106 | } | 107 | } |
| 107 | 108 | ||
| 109 | @Keep | ||
| 110 | @JvmStatic | ||
| 111 | fun getParentDirectory(path: String): String = | ||
| 112 | if (DocumentsTree.isNativePath(path)) { | ||
| 113 | YuzuApplication.documentsTree!!.getParentDirectory(path) | ||
| 114 | } else { | ||
| 115 | path | ||
| 116 | } | ||
| 117 | |||
| 118 | @Keep | ||
| 119 | @JvmStatic | ||
| 120 | fun getFilename(path: String): String = | ||
| 121 | if (DocumentsTree.isNativePath(path)) { | ||
| 122 | YuzuApplication.documentsTree!!.getFilename(path) | ||
| 123 | } else { | ||
| 124 | FileUtil.getFilename(Uri.parse(path)) | ||
| 125 | } | ||
| 126 | |||
| 108 | /** | 127 | /** |
| 109 | * Returns true if pro controller isn't available and handheld is | 128 | * Returns true if pro controller isn't available and handheld is |
| 110 | */ | 129 | */ |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt index eafcf9e42..738275297 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt | |||
| @@ -42,6 +42,23 @@ class DocumentsTree { | |||
| 42 | return node != null && node.isDirectory | 42 | return node != null && node.isDirectory |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | fun getParentDirectory(filepath: String): String { | ||
| 46 | val node = resolvePath(filepath)!! | ||
| 47 | val parentNode = node.parent | ||
| 48 | if (parentNode != null && parentNode.isDirectory) { | ||
| 49 | return parentNode.uri!!.toString() | ||
| 50 | } | ||
| 51 | return node.uri!!.toString() | ||
| 52 | } | ||
| 53 | |||
| 54 | fun getFilename(filepath: String): String { | ||
| 55 | val node = resolvePath(filepath) | ||
| 56 | if (node != null) { | ||
| 57 | return node.name!! | ||
| 58 | } | ||
| 59 | return filepath | ||
| 60 | } | ||
| 61 | |||
| 45 | private fun resolvePath(filepath: String): DocumentsNode? { | 62 | private fun resolvePath(filepath: String): DocumentsNode? { |
| 46 | val tokens = StringTokenizer(filepath, File.separator, false) | 63 | val tokens = StringTokenizer(filepath, File.separator, false) |
| 47 | var iterator = root | 64 | var iterator = root |
diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h index 2eb5c4349..b1db87e41 100644 --- a/src/android/app/src/main/jni/native.h +++ b/src/android/app/src/main/jni/native.h | |||
| @@ -2,14 +2,14 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <android/native_window_jni.h> | 4 | #include <android/native_window_jni.h> |
| 5 | #include "common/detached_tasks.h" | ||
| 5 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/file_sys/registered_cache.h" | ||
| 8 | #include "core/hle/service/acc/profile_manager.h" | ||
| 6 | #include "core/perf_stats.h" | 9 | #include "core/perf_stats.h" |
| 7 | #include "jni/emu_window/emu_window.h" | ||
| 8 | #include "jni/applets/software_keyboard.h" | 10 | #include "jni/applets/software_keyboard.h" |
| 11 | #include "jni/emu_window/emu_window.h" | ||
| 9 | #include "video_core/rasterizer_interface.h" | 12 | #include "video_core/rasterizer_interface.h" |
| 10 | #include "common/detached_tasks.h" | ||
| 11 | #include "core/hle/service/acc/profile_manager.h" | ||
| 12 | #include "core/file_sys/registered_cache.h" | ||
| 13 | 13 | ||
| 14 | #pragma once | 14 | #pragma once |
| 15 | 15 | ||
diff --git a/src/common/fs/fs_android.cpp b/src/common/fs/fs_android.cpp index 298a79bac..1dd826a4a 100644 --- a/src/common/fs/fs_android.cpp +++ b/src/common/fs/fs_android.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/fs/fs_android.h" | 4 | #include "common/fs/fs_android.h" |
| 5 | #include "common/string_util.h" | ||
| 5 | 6 | ||
| 6 | namespace Common::FS::Android { | 7 | namespace Common::FS::Android { |
| 7 | 8 | ||
| @@ -28,28 +29,35 @@ void RegisterCallbacks(JNIEnv* env, jclass clazz) { | |||
| 28 | env->GetJavaVM(&g_jvm); | 29 | env->GetJavaVM(&g_jvm); |
| 29 | native_library = clazz; | 30 | native_library = clazz; |
| 30 | 31 | ||
| 32 | #define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) \ | ||
| 33 | F(JMethodID, JMethodName, Signature) | ||
| 31 | #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) \ | 34 | #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) \ |
| 32 | F(JMethodID, JMethodName, Signature) | 35 | F(JMethodID, JMethodName, Signature) |
| 33 | #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) \ | 36 | #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) \ |
| 34 | F(JMethodID, JMethodName, Signature) | 37 | F(JMethodID, JMethodName, Signature) |
| 35 | #define F(JMethodID, JMethodName, Signature) \ | 38 | #define F(JMethodID, JMethodName, Signature) \ |
| 36 | JMethodID = env->GetStaticMethodID(native_library, JMethodName, Signature); | 39 | JMethodID = env->GetStaticMethodID(native_library, JMethodName, Signature); |
| 40 | ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH) | ||
| 37 | ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | 41 | ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) |
| 38 | ANDROID_STORAGE_FUNCTIONS(FS) | 42 | ANDROID_STORAGE_FUNCTIONS(FS) |
| 39 | #undef F | 43 | #undef F |
| 40 | #undef FS | 44 | #undef FS |
| 41 | #undef FR | 45 | #undef FR |
| 46 | #undef FH | ||
| 42 | } | 47 | } |
| 43 | 48 | ||
| 44 | void UnRegisterCallbacks() { | 49 | void UnRegisterCallbacks() { |
| 50 | #define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) F(JMethodID) | ||
| 45 | #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID) | 51 | #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID) |
| 46 | #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID) | 52 | #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID) |
| 47 | #define F(JMethodID) JMethodID = nullptr; | 53 | #define F(JMethodID) JMethodID = nullptr; |
| 54 | ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH) | ||
| 48 | ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | 55 | ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) |
| 49 | ANDROID_STORAGE_FUNCTIONS(FS) | 56 | ANDROID_STORAGE_FUNCTIONS(FS) |
| 50 | #undef F | 57 | #undef F |
| 51 | #undef FS | 58 | #undef FS |
| 52 | #undef FR | 59 | #undef FR |
| 60 | #undef FH | ||
| 53 | } | 61 | } |
| 54 | 62 | ||
| 55 | bool IsContentUri(const std::string& path) { | 63 | bool IsContentUri(const std::string& path) { |
| @@ -95,4 +103,29 @@ ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | |||
| 95 | #undef F | 103 | #undef F |
| 96 | #undef FR | 104 | #undef FR |
| 97 | 105 | ||
| 106 | #define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) \ | ||
| 107 | F(FunctionName, JMethodID, Caller) | ||
| 108 | #define F(FunctionName, JMethodID, Caller) \ | ||
| 109 | std::string FunctionName(const std::string& filepath) { \ | ||
| 110 | if (JMethodID == nullptr) { \ | ||
| 111 | return 0; \ | ||
| 112 | } \ | ||
| 113 | auto env = GetEnvForThread(); \ | ||
| 114 | jstring j_filepath = env->NewStringUTF(filepath.c_str()); \ | ||
| 115 | jstring j_return = \ | ||
| 116 | static_cast<jstring>(env->Caller(native_library, JMethodID, j_filepath)); \ | ||
| 117 | if (!j_return) { \ | ||
| 118 | return {}; \ | ||
| 119 | } \ | ||
| 120 | const jchar* jchars = env->GetStringChars(j_return, nullptr); \ | ||
| 121 | const jsize length = env->GetStringLength(j_return); \ | ||
| 122 | const std::u16string_view string_view(reinterpret_cast<const char16_t*>(jchars), length); \ | ||
| 123 | const std::string converted_string = Common::UTF16ToUTF8(string_view); \ | ||
| 124 | env->ReleaseStringChars(j_return, jchars); \ | ||
| 125 | return converted_string; \ | ||
| 126 | } | ||
| 127 | ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH) | ||
| 128 | #undef F | ||
| 129 | #undef FH | ||
| 130 | |||
| 98 | } // namespace Common::FS::Android | 131 | } // namespace Common::FS::Android |
diff --git a/src/common/fs/fs_android.h b/src/common/fs/fs_android.h index b441c2a12..2c9234313 100644 --- a/src/common/fs/fs_android.h +++ b/src/common/fs/fs_android.h | |||
| @@ -17,19 +17,28 @@ | |||
| 17 | "(Ljava/lang/String;)Z") \ | 17 | "(Ljava/lang/String;)Z") \ |
| 18 | V(Exists, bool, file_exists, CallStaticBooleanMethod, "exists", "(Ljava/lang/String;)Z") | 18 | V(Exists, bool, file_exists, CallStaticBooleanMethod, "exists", "(Ljava/lang/String;)Z") |
| 19 | 19 | ||
| 20 | #define ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(V) \ | ||
| 21 | V(GetParentDirectory, get_parent_directory, CallStaticObjectMethod, "getParentDirectory", \ | ||
| 22 | "(Ljava/lang/String;)Ljava/lang/String;") \ | ||
| 23 | V(GetFilename, get_filename, CallStaticObjectMethod, "getFilename", \ | ||
| 24 | "(Ljava/lang/String;)Ljava/lang/String;") | ||
| 25 | |||
| 20 | namespace Common::FS::Android { | 26 | namespace Common::FS::Android { |
| 21 | 27 | ||
| 22 | static JavaVM* g_jvm = nullptr; | 28 | static JavaVM* g_jvm = nullptr; |
| 23 | static jclass native_library = nullptr; | 29 | static jclass native_library = nullptr; |
| 24 | 30 | ||
| 31 | #define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) F(JMethodID) | ||
| 25 | #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID) | 32 | #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID) |
| 26 | #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID) | 33 | #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID) |
| 27 | #define F(JMethodID) static jmethodID JMethodID = nullptr; | 34 | #define F(JMethodID) static jmethodID JMethodID = nullptr; |
| 35 | ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH) | ||
| 28 | ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | 36 | ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) |
| 29 | ANDROID_STORAGE_FUNCTIONS(FS) | 37 | ANDROID_STORAGE_FUNCTIONS(FS) |
| 30 | #undef F | 38 | #undef F |
| 31 | #undef FS | 39 | #undef FS |
| 32 | #undef FR | 40 | #undef FR |
| 41 | #undef FH | ||
| 33 | 42 | ||
| 34 | enum class OpenMode { | 43 | enum class OpenMode { |
| 35 | Read, | 44 | Read, |
| @@ -62,4 +71,10 @@ ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | |||
| 62 | #undef F | 71 | #undef F |
| 63 | #undef FR | 72 | #undef FR |
| 64 | 73 | ||
| 74 | #define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) F(FunctionName) | ||
| 75 | #define F(FunctionName) std::string FunctionName(const std::string& filepath); | ||
| 76 | ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH) | ||
| 77 | #undef F | ||
| 78 | #undef FH | ||
| 79 | |||
| 65 | } // namespace Common::FS::Android | 80 | } // namespace Common::FS::Android |
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index 0c4c88cde..c3a81f9a9 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp | |||
| @@ -401,6 +401,16 @@ std::string SanitizePath(std::string_view path_, DirectorySeparator directory_se | |||
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | std::string_view GetParentPath(std::string_view path) { | 403 | std::string_view GetParentPath(std::string_view path) { |
| 404 | if (path.empty()) { | ||
| 405 | return path; | ||
| 406 | } | ||
| 407 | |||
| 408 | #ifdef ANDROID | ||
| 409 | if (path[0] != '/') { | ||
| 410 | std::string path_string{path}; | ||
| 411 | return FS::Android::GetParentDirectory(path_string); | ||
| 412 | } | ||
| 413 | #endif | ||
| 404 | const auto name_bck_index = path.rfind('\\'); | 414 | const auto name_bck_index = path.rfind('\\'); |
| 405 | const auto name_fwd_index = path.rfind('/'); | 415 | const auto name_fwd_index = path.rfind('/'); |
| 406 | std::size_t name_index; | 416 | std::size_t name_index; |
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 4c7aba3f5..72c481798 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp | |||
| @@ -14,6 +14,10 @@ | |||
| 14 | #include <windows.h> | 14 | #include <windows.h> |
| 15 | #endif | 15 | #endif |
| 16 | 16 | ||
| 17 | #ifdef ANDROID | ||
| 18 | #include <common/fs/fs_android.h> | ||
| 19 | #endif | ||
| 20 | |||
| 17 | namespace Common { | 21 | namespace Common { |
| 18 | 22 | ||
| 19 | /// Make a string lowercase | 23 | /// Make a string lowercase |
| @@ -63,6 +67,14 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _ | |||
| 63 | if (full_path.empty()) | 67 | if (full_path.empty()) |
| 64 | return false; | 68 | return false; |
| 65 | 69 | ||
| 70 | #ifdef ANDROID | ||
| 71 | if (full_path[0] != '/') { | ||
| 72 | *_pPath = Common::FS::Android::GetParentDirectory(full_path); | ||
| 73 | *_pFilename = Common::FS::Android::GetFilename(full_path); | ||
| 74 | return true; | ||
| 75 | } | ||
| 76 | #endif | ||
| 77 | |||
| 66 | std::size_t dir_end = full_path.find_last_of("/" | 78 | std::size_t dir_end = full_path.find_last_of("/" |
| 67 | // windows needs the : included for something like just "C:" to be considered a directory | 79 | // windows needs the : included for something like just "C:" to be considered a directory |
| 68 | #ifdef _WIN32 | 80 | #ifdef _WIN32 |