From 71f3d22db8c5ca6a9686f646acfa001ecbbc349b Mon Sep 17 00:00:00 2001
From: Emmanuel Hansen <emmausssss@gmail.com>
Date: Mon, 30 Oct 2023 08:24:43 +0000
Subject: [PATCH] android - add string map

---
 src/LibRyujinx/Android/JniExportedMethods.cs  | 22 ++++++++--
 .../app/src/main/cpp/CMakeLists.txt           |  1 +
 src/RyujinxAndroid/app/src/main/cpp/ryuijnx.h |  2 +
 .../app/src/main/cpp/ryujinx.cpp              | 40 ++++++++++---------
 .../app/src/main/cpp/string_helper.cpp        | 24 +++++++++++
 .../app/src/main/cpp/string_helper.h          | 29 ++++++++++++++
 .../java/org/ryujinx/android/NativeHelpers.kt |  4 +-
 .../java/org/ryujinx/android/RyujinxNative.kt |  2 +-
 .../org/ryujinx/android/views/HomeViews.kt    |  4 +-
 .../org/ryujinx/android/views/UserViews.kt    |  4 +-
 10 files changed, 104 insertions(+), 28 deletions(-)
 create mode 100644 src/RyujinxAndroid/app/src/main/cpp/string_helper.cpp
 create mode 100644 src/RyujinxAndroid/app/src/main/cpp/string_helper.h

diff --git a/src/LibRyujinx/Android/JniExportedMethods.cs b/src/LibRyujinx/Android/JniExportedMethods.cs
index 255adb456..20858eddd 100644
--- a/src/LibRyujinx/Android/JniExportedMethods.cs
+++ b/src/LibRyujinx/Android/JniExportedMethods.cs
@@ -42,7 +42,23 @@ namespace LibRyujinx
         private extern static JStringLocalRef createString(JEnvRef jEnv, IntPtr ch);
 
         [DllImport("libryujinxjni")]
-        private extern static void pushString(string ch);
+        private extern static long storeString(string ch);
+        [DllImport("libryujinxjni")]
+        private extern static IntPtr getString(long id);
+
+        private static string GetStoredString(long id)
+        {
+            var pointer = getString(id);
+            if (pointer != IntPtr.Zero)
+            {
+                var str = Marshal.PtrToStringAnsi(pointer) ?? "";
+
+                Marshal.FreeHGlobal(pointer);
+                return str;
+            }
+
+            return "";
+        }
 
         [DllImport("libryujinxjni")]
         internal extern static void setRenderingThread();
@@ -514,11 +530,11 @@ namespace LibRyujinx
         }
 
         [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_userGetOpenedUser")]
-        public static void JniGetOpenedUser(JEnvRef jEnv, JObjectLocalRef jObj)
+        public static JLong JniGetOpenedUser(JEnvRef jEnv, JObjectLocalRef jObj)
         {
             var userId = GetOpenedUser();
 
-            pushString(userId);
+            return storeString(userId);
         }
 
         [UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_userGetUserPicture")]
diff --git a/src/RyujinxAndroid/app/src/main/cpp/CMakeLists.txt b/src/RyujinxAndroid/app/src/main/cpp/CMakeLists.txt
index 6ae2af030..0c9871c6b 100644
--- a/src/RyujinxAndroid/app/src/main/cpp/CMakeLists.txt
+++ b/src/RyujinxAndroid/app/src/main/cpp/CMakeLists.txt
@@ -29,6 +29,7 @@ add_library( # Sets the name of the library.
             # Provides a relative path to your source file(s).
             vulkan_wrapper.cpp
             oboe.cpp
+            string_helper.cpp
             ryujinx.cpp)
 
 # Searches for a specified prebuilt library and stores the path as a
diff --git a/src/RyujinxAndroid/app/src/main/cpp/ryuijnx.h b/src/RyujinxAndroid/app/src/main/cpp/ryuijnx.h
index 87e7c3124..836cb6ccc 100644
--- a/src/RyujinxAndroid/app/src/main/cpp/ryuijnx.h
+++ b/src/RyujinxAndroid/app/src/main/cpp/ryuijnx.h
@@ -19,6 +19,7 @@
 #include <fcntl.h>
 #include "libraries/adrenotools/include/adrenotools/driver.h"
 #include "native_window.h"
+#include "string_helper.h"
 
 // A macro to pass call to Vulkan and check for return value for success
 #define CALL_VK(func)                                                 \
@@ -46,5 +47,6 @@ JavaVM* _vm = nullptr;
 jobject _mainActivity = nullptr;
 jclass _mainActivityClass = nullptr;
 std::string _currentString = "";
+string_helper str_helper = string_helper();
 
 #endif //RYUJINXNATIVE_RYUIJNX_H
diff --git a/src/RyujinxAndroid/app/src/main/cpp/ryujinx.cpp b/src/RyujinxAndroid/app/src/main/cpp/ryujinx.cpp
index 095f462db..391d71850 100644
--- a/src/RyujinxAndroid/app/src/main/cpp/ryujinx.cpp
+++ b/src/RyujinxAndroid/app/src/main/cpp/ryujinx.cpp
@@ -312,24 +312,28 @@ Java_org_ryujinx_android_NativeHelpers_getProgressInfo(JNIEnv *env, jobject thiz
     return createStringFromStdString(env, progressInfo);
 }
 
+extern "C"
+long storeString(char* str){
+    return str_helper.store_cstring(str);
+}
+
+extern "C"
+const char* getString(long id){
+    auto str = str_helper.get_stored(id);
+    auto cstr = (char*)::malloc(str.length() + 1);
+    ::strcpy(cstr, str.c_str());
+    return cstr;
+}
+
+extern "C"
+JNIEXPORT jlong JNICALL
+Java_org_ryujinx_android_NativeHelpers_storeStringJava(JNIEnv *env, jobject thiz, jstring string) {
+    auto str = getStringPointer(env, string);
+    return str_helper.store_cstring(str);
+}
+
 extern "C"
 JNIEXPORT jstring JNICALL
-Java_org_ryujinx_android_NativeHelpers_popStringJava(JNIEnv *env, jobject thiz) {
-    return createStringFromStdString(env, _currentString);
-}
-extern "C"
-JNIEXPORT void JNICALL
-Java_org_ryujinx_android_NativeHelpers_pushStringJava(JNIEnv *env, jobject thiz, jstring string) {
-    _currentString = getStringPointer(env, string);
-}
-
-
-extern "C"
-void pushString(char* str){
-    _currentString = str;
-}
-
-extern "C"
-const char* popString(){
-    return _currentString.c_str();
+Java_org_ryujinx_android_NativeHelpers_getStringJava(JNIEnv *env, jobject thiz, jlong id) {
+    return createStringFromStdString(env, str_helper.get_stored(id));
 }
diff --git a/src/RyujinxAndroid/app/src/main/cpp/string_helper.cpp b/src/RyujinxAndroid/app/src/main/cpp/string_helper.cpp
new file mode 100644
index 000000000..e8e8483b0
--- /dev/null
+++ b/src/RyujinxAndroid/app/src/main/cpp/string_helper.cpp
@@ -0,0 +1,24 @@
+//
+// Created by Emmanuel Hansen on 10/30/2023.
+//
+
+#include "string_helper.h"
+
+long string_helper::store_cstring(const char *cstr) {
+    auto id = ++current_id;
+    _map.insert({id, cstr});
+    return id;
+}
+
+long string_helper::store_string(const string& str) {
+    auto id = ++current_id;
+    _map.insert({id, str});
+    return id;
+}
+
+string string_helper::get_stored(long id) {
+    auto str = _map[id];
+    _map.erase(id);
+
+    return str;
+}
diff --git a/src/RyujinxAndroid/app/src/main/cpp/string_helper.h b/src/RyujinxAndroid/app/src/main/cpp/string_helper.h
new file mode 100644
index 000000000..b43993d29
--- /dev/null
+++ b/src/RyujinxAndroid/app/src/main/cpp/string_helper.h
@@ -0,0 +1,29 @@
+//
+// Created by Emmanuel Hansen on 10/30/2023.
+//
+
+#ifndef RYUJINXANDROID_STRING_HELPER_H
+#define RYUJINXANDROID_STRING_HELPER_H
+
+#include <string>
+#include <unordered_map>
+using namespace std;
+class string_helper {
+public:
+    long store_cstring(const char * cstr);
+    long store_string(const string& str);
+
+    string get_stored(long id);
+
+    string_helper(){
+        _map = unordered_map<long,string>();
+        current_id = 0;
+    }
+
+private:
+    unordered_map<long, string> _map;
+    long current_id;
+};
+
+
+#endif //RYUJINXANDROID_STRING_HELPER_H
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/NativeHelpers.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/NativeHelpers.kt
index 229b61a90..9bfba4c19 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/NativeHelpers.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/NativeHelpers.kt
@@ -28,6 +28,6 @@ class NativeHelpers {
     external fun setSwapInterval(nativeWindow: Long, swapInterval: Int): Int
     external fun getProgressInfo() : String
     external fun getProgressValue() : Float
-    external fun pushStringJava(string: String)
-    external fun popStringJava() : String
+    external fun storeStringJava(string: String) : Long
+    external fun getStringJava(id: Long) : String
 }
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/RyujinxNative.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/RyujinxNative.kt
index 4c990f094..2ef30c9c7 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/RyujinxNative.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/RyujinxNative.kt
@@ -53,7 +53,7 @@ class RyujinxNative {
     external fun deviceSignalEmulationClose()
     external fun deviceGetDlcTitleId(path: String, ncaPath: String) : String
     external fun deviceGetDlcContentList(path: String, titleId: Long) : Array<String>
-    external fun userGetOpenedUser()
+    external fun userGetOpenedUser() : Long
     external fun userGetUserPicture(userId: String) : String
     external fun userSetUserPicture(userId: String, picture: String)
     external fun userGetUserName(userId: String) : String
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/HomeViews.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/HomeViews.kt
index f567410f1..ea9aa289a 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/HomeViews.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/HomeViews.kt
@@ -106,8 +106,8 @@ class HomeViews {
             }
 
             if (refreshUser.value) {
-                native.userGetOpenedUser()
-                user.value = NativeHelpers().popStringJava()
+                val id = native.userGetOpenedUser()
+                user.value = NativeHelpers().getStringJava(id)
                 if (user.value.isNotEmpty()) {
                     val decoder = Base64.getDecoder()
                     pic.value = decoder.decode(native.userGetUserPicture(user.value))
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/UserViews.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/UserViews.kt
index 63f0f2379..f7c79a156 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/UserViews.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/UserViews.kt
@@ -48,9 +48,9 @@ class UserViews {
         fun Main(viewModel: MainViewModel? = null, navController: NavHostController? = null) {
             val ryujinxNative = RyujinxNative()
             val decoder = Base64.getDecoder()
-            ryujinxNative.userGetOpenedUser()
+            val id = ryujinxNative.userGetOpenedUser()
             val openedUser = remember {
-                mutableStateOf(NativeHelpers().popStringJava())
+                mutableStateOf(NativeHelpers().getStringJava(id))
             }
 
             val openedUserPic = remember {