diff --git a/app/src/main/java/app/gamenative/ui/component/dialog/GeneralTab.kt b/app/src/main/java/app/gamenative/ui/component/dialog/GeneralTab.kt
index 66653ed568..78cb84231f 100644
--- a/app/src/main/java/app/gamenative/ui/component/dialog/GeneralTab.kt
+++ b/app/src/main/java/app/gamenative/ui/component/dialog/GeneralTab.kt
@@ -396,7 +396,28 @@ fun GeneralTabContent(
}
},
)
+ SettingsSwitch(
+ colors = settingsTileColorsAlt(),
+ title = { Text(text = stringResource(R.string.disable_libredirect_title)) },
+ subtitle = { Text(text = stringResource(R.string.disable_libredirect_subtitle)) },
+ state = config.disableLibredirect,
+ onCheckedChange = {
+ state.config.value = if (it) {
+ config.copy(disableLibredirect = true, fasterExternalLoading = false)
+ } else {
+ config.copy(disableLibredirect = false)
+ }
+ },
+ )
}
+ SettingsSwitch(
+ colors = settingsTileColorsAlt(),
+ enabled = !config.disableLibredirect,
+ title = { Text(text = stringResource(R.string.faster_external_loading_title)) },
+ subtitle = { Text(text = stringResource(R.string.faster_external_loading_subtitle)) },
+ state = config.fasterExternalLoading,
+ onCheckedChange = { state.config.value = config.copy(fasterExternalLoading = it) },
+ )
val steamTypeItems = listOf("Normal", "Light", "Ultra Light")
val currentSteamTypeIndex = when (config.steamType.lowercase()) {
Container.STEAM_TYPE_LIGHT -> 1
diff --git a/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt b/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
index d7af2046fb..09a15df78b 100644
--- a/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
+++ b/app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
@@ -3921,15 +3921,6 @@ private fun setupXEnvironment(
envVars.remove("VKD3D_FRAME_RATE")
if (!envVars.has("WINEESYNC")) envVars.put("WINEESYNC", "1")
- val ffpGameDir = runCatching {
- Container.drivesIterator(container.drives).asSequence()
- .firstOrNull { it[0] == "A" }?.let { File(it[1]).canonicalFile.path }
- }.getOrNull() ?: ""
- if (ffpGameDir.startsWith("/storage/") && !ffpGameDir.startsWith("/storage/emulated/")) {
- envVars.put("FFP_ENABLE", "1")
- envVars.put("FFP_MARKERS", "/steamapps/common/;/dosdevices/a:")
- }
-
val graphicsDriverConfig = KeyValueSet(container.getGraphicsDriverConfig())
if (graphicsDriverConfig.get("version").lowercase(Locale.getDefault()).contains("gen8")) {
var tuDebug = envVars.get("TU_DEBUG")
diff --git a/app/src/main/java/app/gamenative/utils/ContainerUtils.kt b/app/src/main/java/app/gamenative/utils/ContainerUtils.kt
index 791774c0d8..3c7fbd5b71 100644
--- a/app/src/main/java/app/gamenative/utils/ContainerUtils.kt
+++ b/app/src/main/java/app/gamenative/utils/ContainerUtils.kt
@@ -335,6 +335,8 @@ object ContainerUtils {
fexcorePreset = container.getFEXCorePreset(),
language = container.language,
sdlControllerAPI = container.isSdlControllerAPI,
+ fasterExternalLoading = container.isFasterExternalLoading,
+ disableLibredirect = container.isDisableLibredirect,
useSteamInput = useSteamInput,
forceDlc = container.isForceDlc,
localSavesOnly = container.isLocalSavesOnly,
@@ -520,6 +522,8 @@ object ContainerUtils {
container.box86Preset = containerData.box86Preset
container.box64Preset = containerData.box64Preset
container.isSdlControllerAPI = containerData.sdlControllerAPI
+ container.isFasterExternalLoading = containerData.fasterExternalLoading
+ container.isDisableLibredirect = containerData.disableLibredirect
container.putExtra("useSteamInput", containerData.useSteamInput)
container.desktopTheme = containerData.desktopTheme
container.graphicsDriverVersion = containerData.graphicsDriverVersion
diff --git a/app/src/main/java/com/winlator/container/Container.java b/app/src/main/java/com/winlator/container/Container.java
index b2be549991..accd82e1e5 100644
--- a/app/src/main/java/com/winlator/container/Container.java
+++ b/app/src/main/java/com/winlator/container/Container.java
@@ -126,6 +126,8 @@ public enum XrControllerMapping {
private String execArgs = ""; // Default exec arguments
private String executablePath = ""; // Executable path for container
private boolean sdlControllerAPI;
+ private boolean fasterExternalLoading;
+ private boolean disableLibredirect;
// Preferred game language for Goldberg force_language.txt
private String language = "english";
@@ -396,6 +398,22 @@ public void setSdlControllerAPI(boolean sdlControllerAPI) {
this.sdlControllerAPI = sdlControllerAPI;
}
+ public boolean isFasterExternalLoading() {
+ return fasterExternalLoading;
+ }
+
+ public void setFasterExternalLoading(boolean fasterExternalLoading) {
+ this.fasterExternalLoading = fasterExternalLoading;
+ }
+
+ public boolean isDisableLibredirect() {
+ return disableLibredirect;
+ }
+
+ public void setDisableLibredirect(boolean disableLibredirect) {
+ this.disableLibredirect = disableLibredirect;
+ }
+
public String getLanguage() {
return language != null ? language : "english";
}
@@ -736,6 +754,8 @@ public void saveData() {
data.put("executablePath", executablePath);
data.put("needsUnpacking", needsUnpacking);
data.put("sdlControllerAPI", sdlControllerAPI);
+ data.put("fasterExternalLoading", fasterExternalLoading);
+ data.put("disableLibredirect", disableLibredirect);
// Disable mouse input flag
data.put("disableMouseInput", disableMouseInput);
// Touchscreen mode flag
@@ -953,6 +973,12 @@ public void loadData(JSONObject data) throws JSONException {
case "sdlControllerAPI" :
setSdlControllerAPI(data.getBoolean(key));
break;
+ case "fasterExternalLoading" :
+ setFasterExternalLoading(data.getBoolean(key));
+ break;
+ case "disableLibredirect" :
+ setDisableLibredirect(data.getBoolean(key));
+ break;
case "disableMouseInput" :
setDisableMouseInput(data.getBoolean(key));
break;
diff --git a/app/src/main/java/com/winlator/container/ContainerData.kt b/app/src/main/java/com/winlator/container/ContainerData.kt
index 11093b1ec1..b4775bb29c 100644
--- a/app/src/main/java/com/winlator/container/ContainerData.kt
+++ b/app/src/main/java/com/winlator/container/ContainerData.kt
@@ -70,6 +70,8 @@ data class ContainerData(
val shaderBackend: String = "glsl",
val useGLSL: String = "enabled",
val sdlControllerAPI: Boolean = true,
+ val fasterExternalLoading: Boolean = false,
+ val disableLibredirect: Boolean = false,
/** Enable Steam Input **/
val useSteamInput: Boolean = false,
/** Enable XInput API **/
@@ -155,6 +157,8 @@ data class ContainerData(
"fexcoreMultiBlock" to state.fexcoreMultiBlock,
"fexcorePreset" to state.fexcorePreset,
"sdlControllerAPI" to state.sdlControllerAPI,
+ "fasterExternalLoading" to state.fasterExternalLoading,
+ "disableLibredirect" to state.disableLibredirect,
"useSteamInput" to state.useSteamInput,
"enableXInput" to state.enableXInput,
"enableDInput" to state.enableDInput,
@@ -226,6 +230,8 @@ data class ContainerData(
fexcoreMultiBlock = (savedMap["fexcoreMultiBlock"] as? String) ?: "Disabled",
fexcorePreset = (savedMap["fexcorePreset"] as? String) ?: FEXCorePreset.INTERMEDIATE,
sdlControllerAPI = savedMap["sdlControllerAPI"] as Boolean,
+ fasterExternalLoading = (savedMap["fasterExternalLoading"] as? Boolean) ?: false,
+ disableLibredirect = (savedMap["disableLibredirect"] as? Boolean) ?: false,
useSteamInput = (savedMap["useSteamInput"] as? Boolean) ?: false,
enableXInput = savedMap["enableXInput"] as Boolean,
enableDInput = savedMap["enableDInput"] as Boolean,
diff --git a/app/src/main/java/com/winlator/xenvironment/ImageFsInstaller.java b/app/src/main/java/com/winlator/xenvironment/ImageFsInstaller.java
index 996d769263..a9ef65cb0c 100644
--- a/app/src/main/java/com/winlator/xenvironment/ImageFsInstaller.java
+++ b/app/src/main/java/com/winlator/xenvironment/ImageFsInstaller.java
@@ -97,6 +97,11 @@ private static void ensureBionicLib(Context context, File imagefs) {
FileUtils.copy(context, "libredirect-bionic-wx.so", wxDest);
chmod(wxDest);
}
+ File wxMinimalDest = new File(imagefs, "usr/lib/libredirect-bionic-wx-minimal.so");
+ if (!wxMinimalDest.exists()) {
+ FileUtils.copy(context, "libredirect-bionic-wx-minimal.so", wxMinimalDest);
+ chmod(wxMinimalDest);
+ }
}
}
diff --git a/app/src/main/java/com/winlator/xenvironment/components/BionicProgramLauncherComponent.java b/app/src/main/java/com/winlator/xenvironment/components/BionicProgramLauncherComponent.java
index c8a2065dee..ab0532710e 100644
--- a/app/src/main/java/com/winlator/xenvironment/components/BionicProgramLauncherComponent.java
+++ b/app/src/main/java/com/winlator/xenvironment/components/BionicProgramLauncherComponent.java
@@ -82,6 +82,20 @@ public WineInfo getWineInfo() {
public Container getContainer() { return this.container; }
public void setContainer(Container container) { this.container = container; }
+ // Resolve which libredirect shim to preload. Normally the flavor default
+ // (PRELOAD_BIONIC_SO). When the container disables libredirect, modern falls
+ // back to the W^X-only minimal shim (still required to run Wine on a strict
+ // W^X kernel) and legacy preloads nothing. Returns null to preload nothing.
+ private String resolveLibredirectPreload(ImageFs imageFs) {
+ if (container != null && container.isDisableLibredirect()) {
+ if (BuildConfig.MODERN_ANDROID) {
+ return imageFs.getLibDir() + "/libredirect-bionic-wx-minimal.so";
+ }
+ return null;
+ }
+ return imageFs.getLibDir() + "/" + BuildConfig.PRELOAD_BIONIC_SO;
+ }
+
/** Numeric Steam appid for the game in this container (e.g. "221380").
* Set from XServerScreen before start(); only consumed in real-Steam mode
* to publish SteamGameId / SteamAppId for the steam_helper handshake. */
@@ -301,18 +315,37 @@ private int execGuestProgram() {
String ld_preload = "";
String sysvPath = imageFs.getLibDir() + "/libandroid-sysvshm.so";
String evshimPath = context.getApplicationInfo().nativeLibraryDir + "/libevshim.so";
- String replacePath = imageFs.getLibDir() + "/" + BuildConfig.PRELOAD_BIONIC_SO;
+ String replacePath = resolveLibredirectPreload(imageFs);
if (new File(sysvPath).exists()) ld_preload += sysvPath;
ld_preload += ":" + evshimPath;
- ld_preload += ":" + replacePath;
+ if (replacePath != null) ld_preload += ":" + replacePath;
envVars.put("LD_PRELOAD", ld_preload);
envVars.put("EVSHIM_WINE", 1);
envVars.put("EVSHIM_SHM_NAME", "controller-shm0");
+ if (container != null && container.isFasterExternalLoading()) {
+ String ffpGameDir = null;
+ for (String[] drive : Container.drivesIterator(container.getDrives())) {
+ if (drive[0].equals("A")) {
+ try {
+ ffpGameDir = new File(drive[1]).getCanonicalPath();
+ } catch (IOException e) {
+ ffpGameDir = drive[1];
+ }
+ break;
+ }
+ }
+ if (ffpGameDir != null && ffpGameDir.startsWith("/storage/")
+ && !ffpGameDir.startsWith("/storage/emulated/")) {
+ envVars.put("FFP_ENABLE", "1");
+ envVars.put("FFP_MARKERS", "/steamapps/common/;/dosdevices/a:");
+ }
+ }
+
// Check for specific shared memory libraries
// if ((new File(imageFs.getLibDir(), "libandroid-sysvshm.so")).exists()){
// ld_preload = imageFs.getLibDir() + "/libandroid-sysvshm.so";
@@ -672,11 +705,11 @@ public String execShellCommand(String command, boolean includeStderr) {
String ld_preload = "";
String sysvPath = imageFs.getLibDir() + "/libandroid-sysvshm.so";
- String replacePath = imageFs.getLibDir() + "/" + BuildConfig.PRELOAD_BIONIC_SO;
+ String replacePath = resolveLibredirectPreload(imageFs);
if (new File(sysvPath).exists()) ld_preload += sysvPath;
- ld_preload += ":" + replacePath;
+ if (replacePath != null) ld_preload += ":" + replacePath;
envVars.put("LD_PRELOAD", ld_preload);
diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml
index 53a4e123a8..561012c6b2 100644
--- a/app/src/main/res/values-da/strings.xml
+++ b/app/src/main/res/values-da/strings.xml
@@ -2232,4 +2232,8 @@
Føjet til favoritter
Føjede %1$s til favoritter
VR-opdateringsfrekvens
+ Hurtigere indlæsning fra eksternt lager
+ Kan gøre spilstart fra eksternt lager markant hurtigere, men kan give problemer i nogle spil
+ Deaktiver libredirect
+ Kan forbedre ydeevnen, men kan også give uventede problemer
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index d7f661002e..c86ecbd051 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -2302,4 +2302,8 @@
Zu Favoriten hinzugefügt
%1$s zu Favoriten hinzugefügt
VR-Bildwiederholrate
+ Schnelleres Laden von externem Speicher
+ Kann den Spielstart von externem Speicher deutlich beschleunigen, kann aber bei manchen Spielen Probleme verursachen
+ libredirect deaktivieren
+ Kann die Leistung verbessern, aber auch unerwartete Probleme verursachen
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 82dde47ce2..e7366db0a8 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -2360,4 +2360,8 @@
Añadido a favoritos
%1$s añadido a favoritos
Frecuencia de actualización de RV
+ Carga más rápida desde almacenamiento externo
+ Puede acelerar considerablemente el inicio de juegos desde almacenamiento externo, pero puede causar problemas en algunos juegos
+ Desactivar libredirect
+ Puede mejorar el rendimiento, pero también puede causar problemas inesperados
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 928934755d..36e2cefdb2 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -2362,4 +2362,8 @@
Ajouté aux favoris
%1$s ajouté aux favoris
Taux de rafraîchissement VR
+ Chargement plus rapide depuis le stockage externe
+ Peut accélérer considérablement le démarrage des jeux depuis le stockage externe, mais peut causer des problèmes dans certains jeux
+ Désactiver libredirect
+ Peut améliorer les performances, mais peut aussi causer des problèmes inattendus
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 1675941165..18772c48f4 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -2353,4 +2353,8 @@
Aggiunto ai preferiti
%1$s aggiunto ai preferiti
Frequenza di aggiornamento VR
+ Caricamento più veloce dalla memoria esterna
+ Può velocizzare notevolmente l\'avvio dei giochi dalla memoria esterna, ma può causare problemi in alcuni giochi
+ Disattiva libredirect
+ Può migliorare le prestazioni, ma può anche causare problemi imprevisti
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index b8d6f6dab9..9e42f29549 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -2316,4 +2316,8 @@
お気に入りに追加しました
%1$s をお気に入りに追加しました
VRリフレッシュレート
+ 外部ストレージからの高速読み込み
+ 外部ストレージからのゲーム起動を大幅に高速化できますが、一部のゲームで問題が発生する可能性があります
+ libredirect を無効にする
+ パフォーマンスが向上する場合がありますが、予期しない問題が発生する可能性もあります
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index bd259d8e18..b7e262bae0 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -2357,4 +2357,8 @@
즐겨찾기에 추가됨
%1$s을(를) 즐겨찾기에 추가함
VR 재생 빈도
+ 외부 저장소에서 더 빠른 로딩
+ 외부 저장소에서의 게임 부팅 속도를 크게 높일 수 있지만 일부 게임에서 문제가 발생할 수 있습니다
+ libredirect 비활성화
+ 성능이 향상될 수 있지만 예기치 않은 문제가 발생할 수도 있습니다
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 131fe34821..ebd6c57cb6 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -2366,4 +2366,8 @@
Dodano do ulubionych
Dodano %1$s do ulubionych
Częstotliwość odświeżania VR
+ Szybsze wczytywanie z pamięci zewnętrznej
+ Może znacznie przyspieszyć uruchamianie gier z pamięci zewnętrznej, ale może powodować problemy w niektórych grach
+ Wyłącz libredirect
+ Może poprawić wydajność, ale może też powodować nieoczekiwane problemy
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index 94708d1101..0ccb209480 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -2232,4 +2232,8 @@
Adicionado aos favoritos
%1$s adicionado aos favoritos
Taxa de atualização de VR
+ Carregamento mais rápido do armazenamento externo
+ Pode acelerar bastante a inicialização de jogos no armazenamento externo, mas pode causar problemas em alguns jogos
+ Desativar libredirect
+ Pode melhorar o desempenho, mas também pode causar problemas inesperados
diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml
index 2987833fa3..be8ac908ae 100644
--- a/app/src/main/res/values-ro/strings.xml
+++ b/app/src/main/res/values-ro/strings.xml
@@ -2366,4 +2366,8 @@
Adăugat la favorite
%1$s adăugat la favorite
Rată de reîmprospătare VR
+ Încărcare mai rapidă de pe stocarea externă
+ Poate accelera semnificativ pornirea jocurilor de pe stocarea externă, dar poate cauza probleme în unele jocuri
+ Dezactivează libredirect
+ Poate îmbunătăți performanța, dar poate cauza și probleme neașteptate
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 69b69abd4d..bc4ad17d80 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -2294,4 +2294,8 @@ https://gamenative.app
Добавлено в избранное
%1$s добавлено в избранное
Частота обновления VR
+ Быстрая загрузка с внешнего накопителя
+ Может значительно ускорить запуск игр с внешнего накопителя, но может вызывать проблемы в некоторых играх
+ Отключить libredirect
+ Может повысить производительность, но также может вызвать непредвиденные проблемы
diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml
index 7f009af0b5..8b741045a4 100644
--- a/app/src/main/res/values-uk/strings.xml
+++ b/app/src/main/res/values-uk/strings.xml
@@ -2362,4 +2362,8 @@
Додано до вибраного
%1$s додано до вибраного
Частота оновлення VR
+ Швидше завантаження із зовнішнього накопичувача
+ Може значно пришвидшити запуск ігор із зовнішнього накопичувача, але може спричиняти проблеми в деяких іграх
+ Вимкнути libredirect
+ Може підвищити продуктивність, але також може спричинити неочікувані проблеми
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 710e7dd7fa..e6b1fef5f5 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -2377,4 +2377,8 @@
已添加到收藏
已将 %1$s 添加到收藏
VR 刷新率
+ 从外部存储更快加载
+ 可显著加快从外部存储启动游戏的速度,但可能导致部分游戏出现问题
+ 禁用 libredirect
+ 可能提升性能,但也可能导致意外问题
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 9243ca7656..d59f3582e2 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -2368,4 +2368,8 @@
已加入收藏
已將 %1$s 加入收藏
VR 重新整理頻率
+ 從外部儲存空間更快載入
+ 可顯著加快從外部儲存空間啟動遊戲的速度,但可能導致部分遊戲出現問題
+ 停用 libredirect
+ 可能提升效能,但也可能導致意外問題
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index dead7a0b3c..286cbe7248 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -224,6 +224,10 @@
Open File
Download File
Processor Affinity
+ Faster loading from external storage
+ Can significantly speed up game boot from external storage, but may cause issues in some games
+ Disable libredirect
+ May improve performance but may also cause unexpected issues
Bring to Front
End Process
New File
diff --git a/app/src/modern/assets/libredirect-bionic-wx-minimal.so b/app/src/modern/assets/libredirect-bionic-wx-minimal.so
new file mode 100755
index 0000000000..530da42f0c
Binary files /dev/null and b/app/src/modern/assets/libredirect-bionic-wx-minimal.so differ