diff --git a/app_pojavlauncher/build.gradle b/app_pojavlauncher/build.gradle index 1825334d..e64b96aa 100644 --- a/app_pojavlauncher/build.gradle +++ b/app_pojavlauncher/build.gradle @@ -254,6 +254,7 @@ dependencies { implementation 'androidx.drawerlayout:drawerlayout:1.2.0' implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01' implementation 'androidx.annotation:annotation:1.5.0' + implementation 'androidx.documentfile:documentfile:1.0.1' implementation "androidx.constraintlayout:constraintlayout:2.1.4" diff --git a/app_pojavlauncher/src/main/java/com/firefly/ui/prefs/ChooseTurnipListPref.java b/app_pojavlauncher/src/main/java/com/firefly/ui/prefs/ChooseTurnipListPref.java new file mode 100644 index 00000000..9b0716cf --- /dev/null +++ b/app_pojavlauncher/src/main/java/com/firefly/ui/prefs/ChooseTurnipListPref.java @@ -0,0 +1,127 @@ +package com.firefly.ui.prefs; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.Toast; + +import androidx.appcompat.app.AlertDialog; +import androidx.preference.ListPreference; + +import net.kdt.pojavlaunch.R; +import net.kdt.pojavlaunch.Tools; +import com.firefly.utils.TurnipUtils; + +import java.util.Arrays; +import java.util.List; + +public class ChooseTurnipListPref extends ListPreference { + private List defaultLibs; + private OnPreferenceChangeListener preferenceChangeListener; + private View.OnClickListener confirmButtonListener; + + public ChooseTurnipListPref(Context context, AttributeSet attrs) { + super(context, attrs); + loadDefaultLibs(context); + } + + private void loadDefaultLibs(Context context) { + defaultLibs = Arrays.asList(context.getResources().getStringArray(R.array.turnip_values)); + } + + @Override + protected void onClick() { + showDialog(); + } + + private void showDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(getDialogTitle()); + + CharSequence[] entriesCharSequence = getEntries(); + String[] entries = new String[entriesCharSequence.length]; + for (int i = 0; i < entriesCharSequence.length; i++) { + entries[i] = entriesCharSequence[i].toString(); + } + + builder.setItems(entries, (dialog, which) -> { + String newValue = getEntryValues()[which].toString(); + if (preferenceChangeListener != null) { + if (preferenceChangeListener.onPreferenceChange(this, newValue)) { + setValue(newValue); + } + } else { + setValue(newValue); + } + dialog.dismiss(); + }); + + LinearLayout layout = new LinearLayout(getContext()); + layout.setOrientation(LinearLayout.VERTICAL); + + Button createButton = new Button(getContext()); + createButton.setText(R.string.pgw_settings_custom_turnip_creat); + createButton.setOnClickListener(view -> { + if (confirmButtonListener != null) { + confirmButtonListener.onClick(view); + } + }); + layout.addView(createButton); + builder.setView(layout); + + AlertDialog dialog = builder.create(); + dialog.show(); + + ListView listView = dialog.getListView(); + listView.setOnItemLongClickListener((adapterView, view, position, id) -> { + String selectedVersion = getEntryValues()[position].toString(); + if (defaultLibs.contains(selectedVersion)) { + Toast.makeText(getContext(), R.string.preference_rendererexp_mesa_delete_defaultlib, Toast.LENGTH_SHORT).show(); + } else { + showDeleteConfirmationDialog(selectedVersion); + } + dialog.dismiss(); + return true; + }); + } + + @Override + public void setOnPreferenceChangeListener(OnPreferenceChangeListener listener) { + this.preferenceChangeListener = listener; + super.setOnPreferenceChangeListener(listener); + } + + public void setConfirmButton(String buttonText, View.OnClickListener listener) { + this.confirmButtonListener = listener; + } + + private void showDeleteConfirmationDialog(String version) { + new AlertDialog.Builder(getContext()) + .setTitle(R.string.pgw_settings_ctu_delete_title) + .setMessage(getContext().getString(R.string.pgw_settings_ctu_delete_message, version)) + .setPositiveButton(R.string.alertdialog_done, (dialog, which) -> { + boolean success = TurnipUtils.INSTANCE.deleteTurnipDriver(version); + if (success) { + Toast.makeText(getContext(), R.string.preference_rendererexp_mesa_deleted, Toast.LENGTH_SHORT).show(); + setEntriesAndValues(); + } else { + Toast.makeText(getContext(), R.string.preference_rendererexp_mesa_delete_fail, Toast.LENGTH_SHORT).show(); + } + }) + .setNegativeButton(R.string.alertdialog_cancel, null) + .show(); + } + + private void setEntriesAndValues() { + Tools.IListAndArry array = Tools.getCompatibleCTurnipDriver(getContext()); + setEntries(array.getArray()); + setEntryValues(array.getList().toArray(new String[0])); + String currentValue = getValue(); + if (!array.getList().contains(currentValue)) { + setValueIndex(0); + } + } +} \ No newline at end of file diff --git a/app_pojavlauncher/src/main/java/com/firefly/utils/TurnipUtils.java b/app_pojavlauncher/src/main/java/com/firefly/utils/TurnipUtils.java new file mode 100644 index 00000000..5ecd4a0d --- /dev/null +++ b/app_pojavlauncher/src/main/java/com/firefly/utils/TurnipUtils.java @@ -0,0 +1,89 @@ +package com.firefly.utils; + +import android.content.Context; +import android.net.Uri; +import android.os.Environment; +import android.widget.Toast; + +import net.kdt.pojavlaunch.Tools; +import net.kdt.pojavlaunch.R; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class TurnipUtils { + + public static final TurnipUtils INSTANCE = new TurnipUtils(); + private final File turnipDir; + + private TurnipUtils() { + this.turnipDir = new File(Tools.TURNIP_DIR); + if (!turnipDir.exists() && !turnipDir.mkdirs()) { + throw new RuntimeException("Failed to create Turnip directory"); + } + } + + public List getTurnipDriverList() { + List list = new ArrayList<>(); + File[] files = turnipDir.listFiles(); + for (File file : files) { + if (file.isDirectory() && new File(file.getAbsolutePath() + "/libvulkan_freedreno.so").exists()) { + list.add(file.getName()); + } + } + return list; + } + + public String getTurnipDriver(String version) { + return Tools.TURNIP_DIR + "/" + version; + } + + public boolean saveTurnipDriver(Context context, Uri fileUri, String folderName) { + try { + File targetDir = new File(turnipDir, folderName); + if (!targetDir.exists() && !targetDir.mkdirs()) { + return false; + } + + File targetFile = new File(targetDir, "libvulkan_freedreno.so"); + + try (InputStream inputStream = context.getContentResolver().openInputStream(fileUri); + OutputStream outputStream = new FileOutputStream(targetFile)) { + if (inputStream == null) return false; + + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean deleteTurnipDriver(String version) { + File libDir = new File(turnipDir, version); + if (libDir.exists()) { + return deleteDirectory(libDir); + } + return false; + } + + private boolean deleteDirectory(File directoryToBeDeleted) { + File[] allContents = directoryToBeDeleted.listFiles(); + if (allContents != null) { + for (File file : allContents) { + deleteDirectory(file); + } + } + return directoryToBeDeleted.delete(); + } +} \ No newline at end of file diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MainActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MainActivity.java index 9acb1833..4f2abee7 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MainActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MainActivity.java @@ -392,6 +392,9 @@ private void runCraft(String versionId, JMinecraftVersionList.Version version) t if (Tools.LOADER_OVERRIDE == null) { Tools.LOADER_OVERRIDE = LauncherPreferences.PREF_LOCAL_LOADER_OVERRIDE; } + if (Tools.TURNIP_LIBS == null) { + Tools.TURNIP_LIBS = LauncherPreferences.PREF_TURNIP_LIBS; + } if (!Tools.checkRendererCompatible(this, Tools.LOCAL_RENDERER)) { Tools.RenderersList renderersList = Tools.getCompatibleRenderers(this); String firstCompatibleRenderer = renderersList.rendererIds.get(0); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java index 89789d25..cf1df6f7 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java @@ -46,6 +46,8 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; +import com.firefly.utils.TurnipUtils; + import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.movtery.ui.subassembly.customprofilepath.ProfilePathHome; @@ -109,6 +111,7 @@ public final class Tools { public static String NATIVE_LIB_DIR; public static String DIR_DATA; //Initialized later to get context public static String MESA_DIR; + public static String TURNIP_DIR; public static File DIR_CACHE; public static File FILE_PROFILE_PATH; public static String MULTIRT_HOME; @@ -129,11 +132,13 @@ public final class Tools { public static String DRIVER_MODEL = null; public static String MESA_LIBS = null; + public static String TURNIP_LIBS = null; public static String LOADER_OVERRIDE = null; private static CDriverModelList sCompatibleCDriverModel; private static CMesaLibList sCompatibleCMesaLibs; private static CMesaLDOList sCompatibleCMesaLDO; + private static CTurnipDriverList sCompatibleCTurnipDriver; private static RenderersList sCompatibleRenderers; private static File getPojavStorageRoot(Context ctx) { @@ -165,6 +170,7 @@ public static void initContextConstants(Context ctx) { DIR_CACHE = ctx.getCacheDir(); DIR_DATA = ctx.getFilesDir().getParent(); MESA_DIR = DIR_DATA + "/mesa"; + TURNIP_DIR = DIR_DATA + "/turnip"; FILE_PROFILE_PATH = new File(Tools.DIR_DATA, "/profile_path.json"); MULTIRT_HOME = DIR_DATA + "/runtimes"; DIR_GAME_HOME = getPojavStorageRoot(ctx).getAbsolutePath(); @@ -1290,7 +1296,6 @@ public String[] getArray() { } public static CMesaLibList getCompatibleCMesaLib(Context context) { - // if (sCompatibleCMesaLibs != null) return sCompatibleCMesaLibs; Resources resources = context.getResources(); String[] defaultCMesaLib = resources.getStringArray(R.array.osmesa_values); String[] defaultCMesaLibNames = resources.getStringArray(R.array.osmesa_library); @@ -1406,6 +1411,45 @@ public static CMesaLDOList getCompatibleCMesaLDO(Context context) { return sCompatibleCMesaLDO; } + public static class CTurnipDriverList implements IListAndArry { + public final List CTurnipDriverIds; + public final String[] CTurnipDriver; + + public CTurnipDriverList(List CTurnipDriverIds, String[] CTurnipDriver) { + this.CTurnipDriverIds = CTurnipDriverIds; + this.CTurnipDriver = CTurnipDriver; + } + + @Override + public List getList() { + return CTurnipDriverIds; + } + + @Override + public String[] getArray() { + return CTurnipDriver; + } + } + + public static CTurnipDriverList getCompatibleCTurnipDriver(Context context) { + Resources resources = context.getResources(); + String[] defaultCTurnipDriver = resources.getStringArray(R.array.turnip_values); + String[] defaultCTurnipDriverNames = resources.getStringArray(R.array.turnip_files); + List CTurnipDriverIds = new ArrayList<>(defaultCTurnipDriver.length); + List CTurnipDriverNames = new ArrayList<>(defaultCTurnipDriverNames.length); + for (int i = 0; i < defaultCTurnipDriver.length; i++) { + CTurnipDriverIds.add(defaultCTurnipDriver[i]); + CTurnipDriverNames.add(defaultCTurnipDriverNames[i]); + } + List addTurnipList = TurnipUtils.INSTANCE.getTurnipDriverList(); + for (String item : addTurnipList) { + CTurnipDriverIds.add(item); + CTurnipDriverNames.add(item); + } + sCompatibleCTurnipDriver = new CTurnipDriverList(CTurnipDriverIds, CTurnipDriverNames.toArray(new String[0])); + return sCompatibleCTurnipDriver; + } + @SuppressLint("DefaultLocale") public static String formatFileSize(long bytes) { if (bytes <= 0) return "0 B"; diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java index 8961180a..669e5a25 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java @@ -26,6 +26,7 @@ public class LauncherPreferences { public static SharedPreferences DEFAULT_PREF; public static String PREF_RENDERER = "opengles2"; public static String PREF_MESA_LIB = "default"; + public static String PREF_TURNIP_LIBS = "default"; public static String PREF_DRIVER_MODEL = "driver_zink"; public static String PREF_LOCAL_LOADER_OVERRIDE = "kgsl"; @@ -149,6 +150,7 @@ public static void loadPreferences(Context ctx) { PREF_EXP_SETUP = DEFAULT_PREF.getBoolean("ExperimentalSetup", false); PREF_MESA_LIB = DEFAULT_PREF.getString("CMesaLibrary", "default"); + PREF_TURNIP_LIBS = DEFAULT_PREF.getString("chooseTurnipDriver", "default"); PREF_DRIVER_MODEL = DEFAULT_PREF.getString("CDriverModels", "driver_zink"); PREF_LOCAL_LOADER_OVERRIDE = DEFAULT_PREF.getString("ChooseMldo", "kgsl"); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/screens/LauncherPreferenceVideoFragment.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/screens/LauncherPreferenceVideoFragment.java index b30b4cd2..b14640eb 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/screens/LauncherPreferenceVideoFragment.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/screens/LauncherPreferenceVideoFragment.java @@ -2,6 +2,15 @@ import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_NOTCH_SIZE; +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.Fragment; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.SwitchPreference; @@ -10,20 +19,19 @@ import androidx.preference.Preference.OnPreferenceChangeListener; import com.firefly.utils.PGWTools; +import com.firefly.utils.TurnipUtils; import com.firefly.ui.dialog.CustomDialog; import com.firefly.ui.prefs.ChooseMesaListPref; +import com.firefly.ui.prefs.ChooseTurnipListPref; import android.content.SharedPreferences; import android.os.Build; -import android.os.Bundle; +import android.text.InputFilter; import android.util.Log; import android.view.LayoutInflater; -import android.view.View; import android.widget.EditText; import android.widget.Toast; -import androidx.appcompat.app.AlertDialog; - import net.kdt.pojavlaunch.PojavApplication; import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.Tools; @@ -38,6 +46,7 @@ */ public class LauncherPreferenceVideoFragment extends LauncherPreferenceFragment { + private static final int FILE_SELECT_CODE = 100; private EditText mSetVideoResolution; private EditText mMesaGLVersion; private EditText mMesaGLSLVersion; @@ -103,11 +112,13 @@ public void onCreatePreferences(Bundle b, String str) { final ListPreference rendererListPref = requirePreference("renderer", ListPreference.class); final ChooseMesaListPref CMesaLibP = requirePreference("CMesaLibrary", ChooseMesaListPref.class); + final ChooseTurnipListPref CTurnipP = requirePreference("chooseTurnipDriver", ChooseTurnipListPref.class); final ListPreference CDriverModelP = requirePreference("CDriverModels", ListPreference.class); final ListPreference CMesaLDOP = requirePreference("ChooseMldo", ListPreference.class); setListPreference(rendererListPref, "renderer"); setListPreference(CMesaLibP, "CMesaLibrary"); + setListPreference(CTurnipP, "chooseTurnipDriver"); setListPreference(CDriverModelP, "CDriverModels"); setListPreference(CMesaLDOP, "ChooseMldo"); @@ -123,6 +134,12 @@ public void onCreatePreferences(Bundle b, String str) { return true; }); + CTurnipP.setOnPreferenceChangeListener((pre, obj) -> { + Tools.TURNIP_LIBS = (String) obj; + return true; + }); + CTurnipP.setConfirmButton(getString(R.string.pgw_settings_custom_turnip_creat), view -> selectTurnipDriverFile()); + CDriverModelP.setOnPreferenceChangeListener((pre, obj) -> { Tools.DRIVER_MODEL = (String) obj; return true; @@ -266,6 +283,9 @@ private void setListPreference(ListPreference listPreference, String preferenceK } else if (preferenceKey.equals("renderer")) { array = Tools.getCompatibleRenderers(getContext()); Tools.LOCAL_RENDERER = value; + } else if (preferenceKey.equals("chooseTurnipDriver")) { + array = Tools.getCompatibleCTurnipDriver(getContext()); + Tools.TURNIP_LIBS = value; } listPreference.setEntries(array.getArray()); listPreference.setEntryValues(array.getList().toArray(new String[0])); @@ -448,4 +468,54 @@ private void downloadMesa(String version) { }); } + private void selectTurnipDriverFile() { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("application/octet-stream"); + intent.addCategory(Intent.CATEGORY_OPENABLE); + startActivityForResult(Intent.createChooser(intent, "Select .so file"), FILE_SELECT_CODE); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == FILE_SELECT_CODE && resultCode == getActivity().RESULT_OK && data != null) { + Uri fileUri = data.getData(); + if (fileUri != null) { + showFolderNameDialog(fileUri); + } + } + } + + private void showFolderNameDialog(Uri fileUri) { + EditText input = new EditText(getActivity()); + input.setFilters(new InputFilter[]{(source, start, end, dest, dstart, dend) -> { + for (int i = start; i < end; i++) { + char c = source.charAt(i); + if (!Character.isLetterOrDigit(c) && c != '.') { + return ""; + } + } + return null; + }}); + new CustomDialog.Builder(getActivity()) + .setTitle(getString(R.string.pgw_settings_ctu_version_name)) + .setCustomView(input) + .setConfirmListener(android.R.string.ok, customView -> { + String folderName = input.getText().toString().trim(); + if (!folderName.isEmpty()) { + boolean success = TurnipUtils.INSTANCE.saveTurnipDriver(getActivity(), fileUri, folderName); + setListPreference(requirePreference("chooseTurnipDriver", ChooseTurnipListPref.class), "chooseTurnipDriver"); + String message = getString(success ? R.string.pgw_settings_ctu_saved : R.string.pgw_settings_ctu_save_fail); + Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show(); + } else { + input.setError(getString(R.string.global_error_field_empty)); + return false; + } + return true; + }) + .setCancelListener(android.R.string.cancel, customView -> true) + .build() + .show(); + } + } diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java index 6911be20..2874118f 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java @@ -6,6 +6,7 @@ import static net.kdt.pojavlaunch.Tools.LOADER_OVERRIDE; import static net.kdt.pojavlaunch.Tools.LOCAL_RENDERER; import static net.kdt.pojavlaunch.Tools.MESA_LIBS; +import static net.kdt.pojavlaunch.Tools.TURNIP_LIBS; import static net.kdt.pojavlaunch.Tools.NATIVE_LIB_DIR; import static net.kdt.pojavlaunch.Tools.currentDisplayMetrics; import static net.kdt.pojavlaunch.Tools.shareLog; @@ -21,6 +22,8 @@ import android.util.Log; import android.widget.Toast; +import com.firefly.utils.TurnipUtils; + import com.movtery.ui.subassembly.customprofilepath.ProfilePathHome; import com.movtery.ui.subassembly.customprofilepath.ProfilePathManager; import com.oracle.dalvik.VMLauncher; @@ -440,6 +443,25 @@ private static void checkAndUsedJSPH(final Runtime runtime) { } } + private static void loadCustomTurnip() throws Throwable { + if (TURNIP_LIBS == null) return; + String folder = null; + switch (TURNIP_LIBS) { + case "default": + // Nothing to do here + break; + default: + folder = TurnipUtils.INSTANCE.getTurnipDriver(TURNIP_LIBS); + break; + } + if (folder == null) return; + try { + Os.setenv("TURNIP_DIR", folder, true); + } catch (Exception e) { + System.err.println("Error setting environment variable: " + e.getMessage()); + } + } + public static int launchJavaVM(final Activity activity, final Runtime runtime, File gameDirectory, final List JVMArgs, final String userArgsString) throws Throwable { String runtimeHome = MultiRTUtils.getRuntimeHome(runtime.name).getAbsolutePath(); @@ -447,6 +469,7 @@ public static int launchJavaVM(final Activity activity, final Runtime runtime, F setJavaEnvironment(runtimeHome); checkAndUsedJSPH(runtime); + loadCustomTurnip(); final String graphicsLib = loadGraphicsLibrary(); if (LOCAL_RENDERER != null && !LOCAL_RENDERER.startsWith("opengles")) diff --git a/app_pojavlauncher/src/main/jni/driver_helper.c b/app_pojavlauncher/src/main/jni/driver_helper.c index bcb8054a..60c12f3b 100644 --- a/app_pojavlauncher/src/main/jni/driver_helper.c +++ b/app_pojavlauncher/src/main/jni/driver_helper.c @@ -48,27 +48,32 @@ bool checkAdrenoGraphics() { return is_adreno; } void* load_turnip_vulkan() { - if(!checkAdrenoGraphics()) return NULL; - const char* native_dir = getenv("POJAV_NATIVEDIR"); + if (!checkAdrenoGraphics()) return NULL; + const char* native_dir = NULL; const char* cache_dir = getenv("TMPDIR"); - if(!linker_ns_load(native_dir)) return NULL; + if (getenv("TURNIP_DIR") != NULL) { + native_dir = getenv("TURNIP_DIR"); + } else { + native_dir = getenv("POJAV_NATIVEDIR"); + } + if (!linker_ns_load(native_dir)) return NULL; void* linkerhook = linker_ns_dlopen("liblinkerhook.so", RTLD_LOCAL | RTLD_NOW); - if(linkerhook == NULL) return NULL; + if (linkerhook == NULL) return NULL; void* turnip_driver_handle = linker_ns_dlopen("libvulkan_freedreno.so", RTLD_LOCAL | RTLD_NOW); - if(turnip_driver_handle == NULL) { + if (turnip_driver_handle == NULL) { printf("AdrenoSupp: Failed to load Turnip!\n%s\n", dlerror()); dlclose(linkerhook); return NULL; } void* dl_android = linker_ns_dlopen("libdl_android.so", RTLD_LOCAL | RTLD_LAZY); - if(dl_android == NULL) { + if (dl_android == NULL) { dlclose(linkerhook); dlclose(turnip_driver_handle); return NULL; } void* android_get_exported_namespace = dlsym(dl_android, "android_get_exported_namespace"); void (*linkerhook_pass_handles)(void*, void*, void*) = dlsym(linkerhook, "app__pojav_linkerhook_pass_handles"); - if(linkerhook_pass_handles == NULL || android_get_exported_namespace == NULL) { + if (linkerhook_pass_handles == NULL || android_get_exported_namespace == NULL) { dlclose(dl_android); dlclose(linkerhook); dlclose(turnip_driver_handle); diff --git a/app_pojavlauncher/src/main/res/values-zh-rCN/pgw_strings.xml b/app_pojavlauncher/src/main/res/values-zh-rCN/pgw_strings.xml index f7dbcd08..9b6a35e8 100644 --- a/app_pojavlauncher/src/main/res/values-zh-rCN/pgw_strings.xml +++ b/app_pojavlauncher/src/main/res/values-zh-rCN/pgw_strings.xml @@ -167,5 +167,14 @@ 安装 安装更新 有新的版本已经下载到 %s. 你要安装它吗? + + 添加 + 输入版本名称 + 驱动已成功保存 + 驱动保存失败 + 删除 Turnip 驱动 + 确定要删除 %s 吗? + 自定义 Turnip 驱动 + 选择 Turnip 驱动(长按删除) \ No newline at end of file diff --git a/app_pojavlauncher/src/main/res/values-zh-rCN/strings.xml b/app_pojavlauncher/src/main/res/values-zh-rCN/strings.xml index 8b1937cf..d073493b 100644 --- a/app_pojavlauncher/src/main/res/values-zh-rCN/strings.xml +++ b/app_pojavlauncher/src/main/res/values-zh-rCN/strings.xml @@ -67,7 +67,7 @@ 重启 保存 正在解压 %s - 此处段不能为空 + 此段不能为空 请稍等 选择 重试 diff --git a/app_pojavlauncher/src/main/res/values-zh-rTW/pgw_strings.xml b/app_pojavlauncher/src/main/res/values-zh-rTW/pgw_strings.xml index c50f631d..d2628bbd 100644 --- a/app_pojavlauncher/src/main/res/values-zh-rTW/pgw_strings.xml +++ b/app_pojavlauncher/src/main/res/values-zh-rTW/pgw_strings.xml @@ -167,5 +167,14 @@ 安裝 安裝更新 新版本已下載到 %s。你要安裝它嗎? + + 新增 + 輸入版本名稱 + 驅動已成功儲存 + 驅動儲存失敗 + 刪除 Turnip 驅動 + 確定要刪除 %s 嗎? + 自訂 Turnip 驅動 + 選擇 Turnip 驅動(長按可刪除) \ No newline at end of file diff --git a/app_pojavlauncher/src/main/res/values/pgw_strings.xml b/app_pojavlauncher/src/main/res/values/pgw_strings.xml index 896c3a90..47140fb2 100644 --- a/app_pojavlauncher/src/main/res/values/pgw_strings.xml +++ b/app_pojavlauncher/src/main/res/values/pgw_strings.xml @@ -141,5 +141,14 @@ Install Install Update A new version has been downloaded at %s. Do you want to install it? + + Add + Enter Version Name + Driver saved successfully + Failed to save driver + Delete Turnip Driver + Are you sure you want to delete %s ? + Custom Turnip Driver + Choose Turnip Driver (Long press to delete) \ No newline at end of file diff --git a/app_pojavlauncher/src/main/res/values/renderer_extra.xml b/app_pojavlauncher/src/main/res/values/renderer_extra.xml index e4636177..a4f01306 100644 --- a/app_pojavlauncher/src/main/res/values/renderer_extra.xml +++ b/app_pojavlauncher/src/main/res/values/renderer_extra.xml @@ -46,4 +46,13 @@ virtio + + @string/global_default + + + + default + + + diff --git a/app_pojavlauncher/src/main/res/xml/pref_video.xml b/app_pojavlauncher/src/main/res/xml/pref_video.xml index 438f2ff7..1ea3b23a 100644 --- a/app_pojavlauncher/src/main/res/xml/pref_video.xml +++ b/app_pojavlauncher/src/main/res/xml/pref_video.xml @@ -157,13 +157,23 @@ /> + +