Sysmem says it costs frames; a session that died in the ENOSYS storm says which switch answers it

Two field bundles: an S25 running with Turnip sysmem on (it turns tiled rendering off - a
corruption fix, not a speed setting, and the text did not say so), and a Fold 5 ending, again,
in dozens of 'Function not implemented' lines from proot's seccomp acceleration failing Steam's
xalia helper. The ended-session message now reads the log's tail off the main thread and, when
it finds that storch, names 'Run proot without seccomp' / 'Skip xalia' in Performance.
This commit is contained in:
The412Banner committed 2026-09-22 06:41:13 -04:00
1 parent 501786dc08
commit 2cbd015d80
2 files changed
+55 -6

No files matched your search

@@ -435,18 +435,67 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
}
private fun onSessionEnded(status: Int) {
runOnUiThread {
if (isFinishing || isDestroyed) return@runOnUiThread
if (status == 0) {
runOnUiThread { if (!isFinishing && !isDestroyed) finish() }
return
}
// What the log says about why, read off the main thread (notifyEnded arrives on it).
Thread({
val hint = sessionEndHint(SessionState.logFile)
runOnUiThread {
if (isFinishing || isDestroyed) return@runOnUiThread
showEnded(status, hint)
}
}, "session-end-hint").start()
}
private fun showEnded(status: Int, hint: String?) {
run {
if (status != 0) {
loading.showEnded("The session ended ($status)\n${SessionState.logFile?.path ?: "-"}")
// A moment on screen, so a failure is readable rather than a flash of black.
Handler(Looper.getMainLooper()).postDelayed({ finish() }, 4000)
loading.showEnded(
"The session ended ($status)\n${SessionState.logFile?.path ?: "-"}" +
(if (hint != null) "\n\n$hint" else "")
)
// A moment on screen, so a failure is readable rather than a flash of black;
// longer when there is advice to read.
Handler(Looper.getMainLooper()).postDelayed({ finish() }, if (hint != null) 9000 else 4000)
} else {
finish()
}
}
}
/**
* One line of advice for a failure the log identifies, or null. The one this recognises: the
* ENOSYS storm - dozens of `socket(): Function not implemented` / `shared memfd open() failed`
* lines - which is proot's seccomp acceleration failing an x86 helper (Steam's xalia under
* FEX) on some devices (a Fold 5, twice). The switch that answers it is in Performance, and a
* user who never opens the log would not know.
*/
private fun sessionEndHint(log: File?): String? {
if (log == null || !log.isFile) return null
return try {
var enosys = 0
// The tail is where a dying session says why; 512 KB covers the storm without reading a 1 GB log.
val size = log.length()
java.io.RandomAccessFile(log, "r").use { f ->
val start = maxOf(0L, size - 512L * 1024)
f.seek(start)
val bytes = ByteArray((size - start).toInt())
f.readFully(bytes)
String(bytes, Charsets.ISO_8859_1).lineSequence().forEach { line ->
if (line.contains("Function not implemented")) enosys++
}
}
if (enosys >= 8) {
"The log shows $enosys \"Function not implemented\" errors: proot's seccomp acceleration is failing a helper on this device. " +
"Try Performance \u2192 \"Run proot without seccomp\" (or \"Skip Steam's xalia helper\") and start again."
} else null
} catch (e: Exception) {
null
}
}
// ── Input ───────────────────────────────────────────────────────────────────────────────
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
@@ -97,7 +97,7 @@ fun PerformanceDialog(
Column(modifier = Modifier.weight(1f)) {
Text("Turnip: sysmem rendering", style = MaterialTheme.typography.bodyMedium)
Text(
"Renders without the GPU's tile memory (TU_DEBUG=sysmem). Banners-Turnip's own advice for an Adreno 8xx that looks glitchy or slow, and required on a 710/720/722 (set on its own there).",
"Renders without the GPU's tile memory (TU_DEBUG=sysmem). A fix for an Adreno 8xx that shows corruption, and required on a 710/720/722 (set on its own there). Not a speed setting: on every other GPU it turns tiled rendering off and COSTS frames - leave it off unless the picture is wrong.",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)