mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
Android: make the settings usable again, and declutter the library menus
CollapsibleSection had stopped collapsing. Its own comment describes "a tappable header that shows or hides its content ... to de-bloat long settings lists", but the body rendered a plain title and called content() unconditionally, with initiallyExpanded marked UNUSED_PARAMETER. All 20 sections across Pad, Renderer, Performance and Fixes were therefore permanently open, which is why the settings became unusable in landscape: not too many options, but every option in a tab on screen at once. Restoring it shortens four tabs at a stroke. State is rememberSaveable so a rotation no longer re-collapses what was just opened, landscape being where the long lists hurt most; Renderer opens on Display & Resolution and Performance on Speedhacks so neither looks empty. The Fixes tab is now Advanced, and absorbed the GameDB fixes from Performance and the whole Recompiler tab. Both are debugging controls that the GameDB already applies per game, so they do not belong in the tab people open to change speed. Fourteen tabs become twelve; the search index and the per-tab reset ownership moved with the settings, so searching "Skip MPEG" lands on Advanced and resetting Performance no longer resets fixes it does not show. Skip BIOS now defaults on. "How do I skip the boot animation" is one of the most-asked questions in the Discord and desktop PCSX2 fast-boots too. Only fresh installs change: the saved JSON always carries the key, so nobody's boot behaviour is altered by an update. The library overflow menu drops from eleven rows to eight with separators. Open navigation goes entirely (the hamburger is on the same toolbar) and Game names in grid moves to App settings beside cover size and opacity, where every other library-appearance preference already lives. Setup / Change Folders and Exit MOVE to the drawer rather than being deleted - each had exactly one entry point, so removing them would have stranded anyone needing to change their ROM folder and left no in-app quit. Exit keeps its confirmation and gets a real power-symbol drawable: the "⏻" glyph is absent from most Android system fonts and rendered as tofu. About leaves the settings tab strip for the drawer, next to the other links. It is a read-only page that was costing a tab slot on every visit. Installed patches and cheats can be collapsed, so a pnach carrying hundreds of downloaded codes can be folded away. Reported by a community member on Discord.
This commit is contained in:
@@ -167,8 +167,13 @@ data class Settings(
|
||||
val enableWideScreenPatches: Boolean = false,
|
||||
/** EmuCore/EnableNoInterlacingPatches — no-interlacing patches. */
|
||||
val enableNoInterlacingPatches: Boolean = false,
|
||||
/** EmuCore/EnableFastBoot — skip BIOS splash and boot straight to the game. */
|
||||
val enableFastBoot: Boolean = false,
|
||||
/** EmuCore/EnableFastBoot — skip BIOS splash and boot straight to the game.
|
||||
*
|
||||
* Default ON: "how do I skip the boot animation" is one of the most-asked questions in the
|
||||
* Discord, and desktop PCSX2 fast-boots by default too. Only fresh installs are affected —
|
||||
* the saved JSON always carries this key, so anyone who already has a value keeps it rather
|
||||
* than having their boot behaviour changed under them by an update. */
|
||||
val enableFastBoot: Boolean = true,
|
||||
/** EmuCore/HostFs — host: filesystem access in the VM, for ELF/homebrew and mods
|
||||
* (e.g. modded Persona 3 FES). Per-game capable; applies on the next game boot. */
|
||||
val hostFs: Boolean = false,
|
||||
|
||||
@@ -35,7 +35,6 @@ enum class SettingsCategory {
|
||||
OnScreen,
|
||||
Skins,
|
||||
Advanced,
|
||||
Recompiler,
|
||||
Patches,
|
||||
About,
|
||||
}
|
||||
|
||||
@@ -68,6 +68,10 @@ import com.armsx2.ui.settings.controllerFocusable
|
||||
// gold trophy rather than the flat monochrome nav glyphs.
|
||||
private val TrophyGold = Color(0xFFFFC93C)
|
||||
|
||||
// Exit is the only row here that ends your session, so it gets the standard power-red rather
|
||||
// than the neutral row tint — the same reason the trophy keeps its gold.
|
||||
private val ExitRed = Color(0xFFE60012)
|
||||
|
||||
// Community/project links for the drawer's About section. Plain https on purpose: Android App
|
||||
// Links hand these to the Discord/GitHub apps when they're installed and fall back to the
|
||||
// browser when they aren't, so there's no app-specific scheme to special-case.
|
||||
@@ -162,6 +166,27 @@ fun NavigationDrawer(
|
||||
private fun DrawerContent(selected: AppRoute, onNavigate: (AppRoute) -> Unit, onDismiss: () -> Unit) {
|
||||
val isLandscape = LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
val context = LocalContext.current
|
||||
// Exit moved here from the library overflow menu; it keeps its confirmation, which is the whole
|
||||
// point of the row — quitting mid-session without one loses whatever is not saved.
|
||||
val exitConfirm = androidx.compose.runtime.remember { androidx.compose.runtime.mutableStateOf(false) }
|
||||
if (exitConfirm.value) {
|
||||
androidx.compose.material3.AlertDialog(
|
||||
onDismissRequest = { exitConfirm.value = false },
|
||||
title = { androidx.compose.material3.Text(str("games.exit.title")) },
|
||||
text = { androidx.compose.material3.Text(str("games.exit.message")) },
|
||||
confirmButton = {
|
||||
androidx.compose.material3.TextButton(onClick = {
|
||||
exitConfirm.value = false
|
||||
MainActivityRuntime.exitApp()
|
||||
}) { androidx.compose.material3.Text(str("games.toolbar.exit")) }
|
||||
},
|
||||
dismissButton = {
|
||||
androidx.compose.material3.TextButton(onClick = { exitConfirm.value = false }) {
|
||||
androidx.compose.material3.Text(str("action.cancel"))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
// Intuitive glyphs that read as what they do — matching the in-game overlay's emoji-icon style
|
||||
// (the old box-drawing characters like ▦ ◉ ⌁ ✦ were unclear per tester feedback).
|
||||
val primary = listOf(
|
||||
@@ -174,6 +199,10 @@ private fun DrawerContent(selected: AppRoute, onNavigate: (AppRoute) -> Unit, on
|
||||
DrawerItem("action.settings", "⚙️", AppRoute.Settings()),
|
||||
)
|
||||
val managers = listOf(
|
||||
// Moved off the library overflow menu, which was its only entry point. Sits first, beside
|
||||
// BIOS Location: both answer "where are my files".
|
||||
DrawerItem("games.overflow.setup", "📂",
|
||||
onAction = { MainActivityRuntime.reopenSetup(); onDismiss() }),
|
||||
DrawerItem("setup.step.bios.title", "📀", AppRoute.BiosManager()),
|
||||
DrawerItem("memcard.title", "💾", AppRoute.MemoryCardManager),
|
||||
DrawerItem("savestate.title.loadManage", "📥", AppRoute.SaveManager),
|
||||
@@ -189,6 +218,15 @@ private fun DrawerContent(selected: AppRoute, onNavigate: (AppRoute) -> Unit, on
|
||||
DrawerItem("about.github", "🐙", iconRes = com.armsx2.R.drawable.ic_github,
|
||||
onAction = { openExternalUrl(context, GithubUrl); onDismiss() }),
|
||||
DrawerItem("about.website", "🌐", onAction = { openExternalUrl(context, WebsiteUrl); onDismiss() }),
|
||||
// About left the settings tab strip: it is a read-only page, not a setting, and it sat in
|
||||
// the tab row costing a slot on every settings visit.
|
||||
DrawerItem("about.title", "ℹ️", AppRoute.About),
|
||||
)
|
||||
// Exit gets its own trailing section. It was briefly filed under ABOUT, next to the Discord and
|
||||
// GitHub links, where nobody would think to look for "quit".
|
||||
val session = listOf(
|
||||
DrawerItem("games.toolbar.exit", "⏻", iconRes = com.armsx2.R.drawable.ic_power,
|
||||
iconTint = ExitRed, onAction = { exitConfirm.value = true }),
|
||||
)
|
||||
|
||||
Column(
|
||||
@@ -216,6 +254,10 @@ private fun DrawerContent(selected: AppRoute, onNavigate: (AppRoute) -> Unit, on
|
||||
HorizontalDivider(color = MaterialTheme.colorScheme.outline.copy(alpha = 0.45f))
|
||||
Spacer(Modifier.height(14.dp))
|
||||
DrawerSection(str("about.section.header"), about, selected, onNavigate)
|
||||
Spacer(Modifier.height(14.dp))
|
||||
HorizontalDivider(color = MaterialTheme.colorScheme.outline.copy(alpha = 0.45f))
|
||||
Spacer(Modifier.height(14.dp))
|
||||
DrawerSection(str("games.section.app"), session, selected, onNavigate)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -758,9 +758,6 @@ private fun LibraryOverflowMenu(
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
fontWeight = FontWeight.Bold,
|
||||
)
|
||||
LibraryOverflowItem("☰", str("games.overflow.openNavigation")) {
|
||||
closeThen(onOpenNavigation)
|
||||
}
|
||||
LibraryOverflowItem(
|
||||
glyph = "A–Z",
|
||||
label = str("games.overflow.sortTitle"),
|
||||
@@ -775,6 +772,7 @@ private fun LibraryOverflowMenu(
|
||||
) {
|
||||
closeThen { onSort(HomeSort.RecentlyPlayed) }
|
||||
}
|
||||
OverflowSeparator()
|
||||
LibraryOverflowItem(
|
||||
glyph = if (use3dCovers) "3D" else "2D",
|
||||
label = str("games.overflow.coverStyle"),
|
||||
@@ -782,13 +780,6 @@ private fun LibraryOverflowMenu(
|
||||
) {
|
||||
closeThen(onToggleCoverStyle)
|
||||
}
|
||||
LibraryOverflowItem(
|
||||
glyph = "Aa",
|
||||
label = str("games.overflow.gridNames"),
|
||||
trailing = if (showGridNames) str("common.on") else str("common.off"),
|
||||
) {
|
||||
closeThen(onToggleGridNames)
|
||||
}
|
||||
LibraryOverflowItem(
|
||||
glyph = "Aa",
|
||||
label = str("games.overflow.customNames"),
|
||||
@@ -810,6 +801,7 @@ private fun LibraryOverflowMenu(
|
||||
) {
|
||||
closeThen(onToggleShowHidden)
|
||||
}
|
||||
OverflowSeparator()
|
||||
LibraryOverflowItem("▧", str("games.background.choose")) {
|
||||
closeThen(onChooseBackground)
|
||||
}
|
||||
@@ -818,15 +810,17 @@ private fun LibraryOverflowMenu(
|
||||
closeThen(onClearBackground)
|
||||
}
|
||||
}
|
||||
LibraryOverflowItem("↻", str("games.overflow.setup")) {
|
||||
closeThen { MainActivityRuntime.reopenSetup() }
|
||||
}
|
||||
LibraryOverflowItem("⏻", str("games.toolbar.exit")) {
|
||||
closeThen(onExitApp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun OverflowSeparator() {
|
||||
androidx.compose.material3.HorizontalDivider(
|
||||
modifier = Modifier.padding(horizontal = 18.dp, vertical = 6.dp),
|
||||
color = MaterialTheme.colorScheme.outline.copy(alpha = 0.30f),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LibraryOverflowItem(
|
||||
glyph: String,
|
||||
|
||||
@@ -401,11 +401,33 @@ private fun CollapsibleOnlineSection(
|
||||
|
||||
@Composable
|
||||
private fun PatchFiles(state: PatchManagerUiState, viewModel: PatchManagerViewModel, modifier: Modifier) {
|
||||
// The whole installed list folds away. A pnach pulled from the downloader can carry hundreds of
|
||||
// codes, and with the list open there was no way past it to the rest of the screen.
|
||||
var listOpen by androidx.compose.runtime.saveable.rememberSaveable { mutableStateOf(true) }
|
||||
Column(modifier) {
|
||||
SectionTitle(str("patches.installedHeader"), state.files.size.toString())
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { listOpen = !listOpen },
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
SectionTitle(
|
||||
str("patches.installedHeader"),
|
||||
state.files.size.toString(),
|
||||
Modifier.weight(1f),
|
||||
)
|
||||
if (state.files.isNotEmpty()) {
|
||||
Text(
|
||||
if (listOpen) "▾" else "▸",
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.padding(horizontal = 8.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
if (state.files.isEmpty()) {
|
||||
PatchFilesEmptyState()
|
||||
} else {
|
||||
} else if (listOpen) {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
state.files.forEach { file ->
|
||||
val expanded = state.localExpandedPath == file.absolutePath
|
||||
|
||||
@@ -501,6 +501,15 @@ fun AppTab() {
|
||||
onChange = LibraryChromePreferences::setShowRecents,
|
||||
)
|
||||
|
||||
// Moved off the library overflow menu, where it was the odd one out: every other
|
||||
// library-appearance preference already lives here beside cover size and opacity.
|
||||
ToggleRow(
|
||||
label = str("games.overflow.gridNames"),
|
||||
value = com.armsx2.GridLabels.show.value,
|
||||
description = str("app.library.gridNames.desc"),
|
||||
onChange = { com.armsx2.GridLabels.set(it) },
|
||||
)
|
||||
|
||||
IntSliderRow(
|
||||
label = str("app.library.coverSize"),
|
||||
value = (com.armsx2.ui.UiScale.coverScale.value * 100f).toInt().coerceIn(75, 250),
|
||||
|
||||
@@ -11,7 +11,10 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.armsx2.config.Settings
|
||||
@@ -449,9 +452,84 @@ fun FixesTab(state: MutableState<Settings>) {
|
||||
onChange = { apply(s.copy(swThreadsHeight = it)) },
|
||||
)
|
||||
}
|
||||
SettingsDivider()
|
||||
// GameDB fixes moved here from Performance: they are per-game compatibility switches the
|
||||
// GameDB already applies automatically, so they belong with the other advanced knobs
|
||||
// rather than in the tab people open to change speed settings.
|
||||
CollapsibleSection(str("perf.gamedbFixes.title")) {
|
||||
HelpText(str("perf.gamedbFixes.help"))
|
||||
ToggleRow(str("perf.fix.skipBios"), s.enableFastBoot, description = str("perf.fix.skipBios.desc")) { apply(s.copy(enableFastBoot = it)) }
|
||||
ToggleRow(str("perf.fix.gamedbFixes"), s.enableGameFixes, description = str("perf.fix.gamedbFixes.desc")) { apply(s.copy(enableGameFixes = it)) }
|
||||
ToggleRow(str("perf.fix.skipMpeg"), s.gamefixSkipMpeg, description = str("perf.fix.skipMpeg.desc")) { apply(s.copy(enableGameFixes = true, gamefixSkipMpeg = it)) }
|
||||
if (s.gamefixSkipMpeg) HelpText(str("perf.fix.skipMpeg.warning"))
|
||||
ToggleRow(str("perf.fix.fmvSoftware"), s.gamefixSoftwareRendererFmv, description = str("perf.fix.fmvSoftware.desc")) { apply(s.copy(enableGameFixes = true, gamefixSoftwareRendererFmv = it)) }
|
||||
ToggleRow(str("perf.fix.eeTiming"), s.gamefixEETiming, description = str("perf.fix.eeTiming.desc")) { apply(s.copy(enableGameFixes = true, gamefixEETiming = it)) }
|
||||
ToggleRow(str("perf.fix.instantDma"), s.gamefixInstantDma, description = str("perf.fix.instantDma.desc")) { apply(s.copy(enableGameFixes = true, gamefixInstantDma = it)) }
|
||||
ToggleRow(str("perf.fix.blitFps"), s.gamefixBlitInternalFps, description = str("perf.fix.blitFps.desc")) { apply(s.copy(enableGameFixes = true, gamefixBlitInternalFps = it)) }
|
||||
ToggleRow(str("perf.fix.fpuMultiply"), s.gamefixFpuMul, description = str("perf.fix.fpuMultiply.desc")) { apply(s.copy(enableGameFixes = true, gamefixFpuMul = it)) }
|
||||
ToggleRow(str("perf.fix.ophFlag"), s.gamefixOphFlag, description = str("perf.fix.ophFlag.desc")) { apply(s.copy(enableGameFixes = true, gamefixOphFlag = it)) }
|
||||
ToggleRow(str("perf.fix.gifFifo"), s.gamefixGifFifo, description = str("perf.fix.gifFifo.desc")) { apply(s.copy(enableGameFixes = true, gamefixGifFifo = it)) }
|
||||
ToggleRow(str("perf.fix.dmaBusy"), s.gamefixDmaBusy, description = str("perf.fix.dmaBusy.desc")) { apply(s.copy(enableGameFixes = true, gamefixDmaBusy = it)) }
|
||||
ToggleRow(str("perf.fix.vif1Stall"), s.gamefixVif1Stall, description = str("perf.fix.vif1Stall.desc")) { apply(s.copy(enableGameFixes = true, gamefixVif1Stall = it)) }
|
||||
ToggleRow(str("perf.fix.iBit"), s.gamefixIbit, description = str("perf.fix.iBit.desc")) { apply(s.copy(enableGameFixes = true, gamefixIbit = it)) }
|
||||
ToggleRow(str("perf.fix.fullVu0Sync"), s.gamefixFullVu0Sync, description = str("perf.fix.fullVu0Sync.desc")) { apply(s.copy(enableGameFixes = true, gamefixFullVu0Sync = it)) }
|
||||
ToggleRow(str("perf.fix.vuAddSub"), s.gamefixVuAddSub, description = str("perf.fix.vuAddSub.desc")) { apply(s.copy(enableGameFixes = true, gamefixVuAddSub = it)) }
|
||||
ToggleRow(str("perf.fix.vuOverflow"), s.gamefixVuOverflow, description = str("perf.fix.vuOverflow.desc")) { apply(s.copy(enableGameFixes = true, gamefixVuOverflow = it)) }
|
||||
ToggleRow(str("perf.fix.extraXgkick"), s.gamefixXgkick, description = str("perf.fix.extraXgkick.desc")) { apply(s.copy(enableGameFixes = true, gamefixXgkick = it)) }
|
||||
ToggleRow(str("perf.fix.goemonTlb"), s.gamefixGoemonTlb, description = str("perf.fix.goemonTlb.desc")) { apply(s.copy(enableGameFixes = true, gamefixGoemonTlb = it)) }
|
||||
ToggleRow(str("perf.fix.vuSync"), s.gamefixVuSync, description = str("perf.fix.vuSync.desc")) { apply(s.copy(enableGameFixes = true, gamefixVuSync = it)) }
|
||||
}
|
||||
SettingsDivider()
|
||||
RecompilerSection(state)
|
||||
Spacer(Modifier.height(8.dp))
|
||||
}
|
||||
}
|
||||
|
||||
// CollapsibleSection now lives in SettingsWidgets.kt (shared by the Fixes / Pad /
|
||||
// Performance / Renderer tabs).
|
||||
|
||||
/** The former standalone Recompiler tab, folded in as a section. Turning a recompiler off drops
|
||||
* that processor to an interpreter — correct but far slower — so it is a debugging control, not
|
||||
* something to browse past on the way to a speed setting. */
|
||||
@Composable
|
||||
private fun RecompilerSection(state: MutableState<Settings>) {
|
||||
val settings = state.value
|
||||
fun apply(updated: Settings) = InGameOverlay.saveSettings(updated)
|
||||
|
||||
CollapsibleSection(str("tab.recompiler")) {
|
||||
Text(
|
||||
str("jit.recompiler.warning"),
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 8.dp),
|
||||
)
|
||||
ToggleRow("EE (R5900)", settings.recEE) { apply(settings.copy(recEE = it)) }
|
||||
ToggleRow("IOP (R3000)", settings.recIOP) { apply(settings.copy(recIOP = it)) }
|
||||
ToggleRow("VU0", settings.recVU0) { apply(settings.copy(recVU0 = it)) }
|
||||
ToggleRow("VU1", settings.recVU1) { apply(settings.copy(recVU1 = it)) }
|
||||
ToggleRow("Fastmem", settings.enableFastmem) { apply(settings.copy(enableFastmem = it)) }
|
||||
|
||||
Spacer(Modifier.height(14.dp))
|
||||
Text(
|
||||
str("jit.diagnostics.header"),
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
|
||||
)
|
||||
// Seed from the REAL native flag: a plain `remember { false }` meant leaving the screen
|
||||
// destroyed the state and the switch came back OFF while the native flag was still on.
|
||||
var eeDiff by remember {
|
||||
mutableStateOf(
|
||||
runCatching { kr.co.iefriends.pcsx2.NativeApp.isEeDiffVerify() }.getOrDefault(false)
|
||||
)
|
||||
}
|
||||
ToggleRow(
|
||||
label = str("jit.eeDiffVerify.label"),
|
||||
value = eeDiff,
|
||||
description = str("jit.eeDiffVerify.description"),
|
||||
) {
|
||||
eeDiff = it
|
||||
runCatching { kr.co.iefriends.pcsx2.NativeApp.setEeDiffVerify(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ fun PerformanceTab(state: MutableState<Settings>) {
|
||||
onChange = { apply(s.copy(affinityMode = it)) },
|
||||
)
|
||||
SettingsDivider()
|
||||
CollapsibleSection(str("perf.speedhacks.title"), initiallyExpanded = false) {
|
||||
CollapsibleSection(str("perf.speedhacks.title"), initiallyExpanded = true) {
|
||||
IntSliderRow(
|
||||
label = str("perf.eeCycleRate.label"),
|
||||
value = s.eeCycleRate,
|
||||
@@ -348,30 +348,6 @@ fun PerformanceTab(state: MutableState<Settings>) {
|
||||
)
|
||||
}
|
||||
SettingsDivider()
|
||||
CollapsibleSection(str("perf.gamedbFixes.title")) {
|
||||
HelpText(str("perf.gamedbFixes.help"))
|
||||
ToggleRow(str("perf.fix.skipBios"), s.enableFastBoot, description = str("perf.fix.skipBios.desc")) { apply(s.copy(enableFastBoot = it)) }
|
||||
ToggleRow(str("perf.fix.gamedbFixes"), s.enableGameFixes, description = str("perf.fix.gamedbFixes.desc")) { apply(s.copy(enableGameFixes = it)) }
|
||||
ToggleRow(str("perf.fix.skipMpeg"), s.gamefixSkipMpeg, description = str("perf.fix.skipMpeg.desc")) { apply(s.copy(enableGameFixes = true, gamefixSkipMpeg = it)) }
|
||||
if (s.gamefixSkipMpeg) HelpText(str("perf.fix.skipMpeg.warning"))
|
||||
ToggleRow(str("perf.fix.fmvSoftware"), s.gamefixSoftwareRendererFmv, description = str("perf.fix.fmvSoftware.desc")) { apply(s.copy(enableGameFixes = true, gamefixSoftwareRendererFmv = it)) }
|
||||
ToggleRow(str("perf.fix.eeTiming"), s.gamefixEETiming, description = str("perf.fix.eeTiming.desc")) { apply(s.copy(enableGameFixes = true, gamefixEETiming = it)) }
|
||||
ToggleRow(str("perf.fix.instantDma"), s.gamefixInstantDma, description = str("perf.fix.instantDma.desc")) { apply(s.copy(enableGameFixes = true, gamefixInstantDma = it)) }
|
||||
ToggleRow(str("perf.fix.blitFps"), s.gamefixBlitInternalFps, description = str("perf.fix.blitFps.desc")) { apply(s.copy(enableGameFixes = true, gamefixBlitInternalFps = it)) }
|
||||
ToggleRow(str("perf.fix.fpuMultiply"), s.gamefixFpuMul, description = str("perf.fix.fpuMultiply.desc")) { apply(s.copy(enableGameFixes = true, gamefixFpuMul = it)) }
|
||||
ToggleRow(str("perf.fix.ophFlag"), s.gamefixOphFlag, description = str("perf.fix.ophFlag.desc")) { apply(s.copy(enableGameFixes = true, gamefixOphFlag = it)) }
|
||||
ToggleRow(str("perf.fix.gifFifo"), s.gamefixGifFifo, description = str("perf.fix.gifFifo.desc")) { apply(s.copy(enableGameFixes = true, gamefixGifFifo = it)) }
|
||||
ToggleRow(str("perf.fix.dmaBusy"), s.gamefixDmaBusy, description = str("perf.fix.dmaBusy.desc")) { apply(s.copy(enableGameFixes = true, gamefixDmaBusy = it)) }
|
||||
ToggleRow(str("perf.fix.vif1Stall"), s.gamefixVif1Stall, description = str("perf.fix.vif1Stall.desc")) { apply(s.copy(enableGameFixes = true, gamefixVif1Stall = it)) }
|
||||
ToggleRow(str("perf.fix.iBit"), s.gamefixIbit, description = str("perf.fix.iBit.desc")) { apply(s.copy(enableGameFixes = true, gamefixIbit = it)) }
|
||||
ToggleRow(str("perf.fix.fullVu0Sync"), s.gamefixFullVu0Sync, description = str("perf.fix.fullVu0Sync.desc")) { apply(s.copy(enableGameFixes = true, gamefixFullVu0Sync = it)) }
|
||||
ToggleRow(str("perf.fix.vuAddSub"), s.gamefixVuAddSub, description = str("perf.fix.vuAddSub.desc")) { apply(s.copy(enableGameFixes = true, gamefixVuAddSub = it)) }
|
||||
ToggleRow(str("perf.fix.vuOverflow"), s.gamefixVuOverflow, description = str("perf.fix.vuOverflow.desc")) { apply(s.copy(enableGameFixes = true, gamefixVuOverflow = it)) }
|
||||
ToggleRow(str("perf.fix.extraXgkick"), s.gamefixXgkick, description = str("perf.fix.extraXgkick.desc")) { apply(s.copy(enableGameFixes = true, gamefixXgkick = it)) }
|
||||
ToggleRow(str("perf.fix.goemonTlb"), s.gamefixGoemonTlb, description = str("perf.fix.goemonTlb.desc")) { apply(s.copy(enableGameFixes = true, gamefixGoemonTlb = it)) }
|
||||
ToggleRow(str("perf.fix.vuSync"), s.gamefixVuSync, description = str("perf.fix.vuSync.desc")) { apply(s.copy(enableGameFixes = true, gamefixVuSync = it)) }
|
||||
}
|
||||
SettingsDivider()
|
||||
CollapsibleSection(str("perf.advancedSpeedhacks.title")) {
|
||||
Spacer(Modifier.height(8.dp))
|
||||
ToggleRow(str("perf.hack.mtvu"), s.mtvu, description = str("perf.hack.mtvu.desc")) { apply(s.copy(mtvu = it)) }
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
package com.armsx2.ui.settings
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.armsx2.config.Settings
|
||||
import com.armsx2.i18n.str
|
||||
import com.armsx2.ui.InGameOverlay
|
||||
import kr.co.iefriends.pcsx2.NativeApp
|
||||
|
||||
@Composable
|
||||
fun RecompilerTab(state: MutableState<Settings>) {
|
||||
val settings = state.value
|
||||
ControllerAutoScroll(settingsScrollState())
|
||||
|
||||
fun apply(updated: Settings) = InGameOverlay.saveSettings(updated)
|
||||
|
||||
Column(Modifier.fillMaxWidth()) {
|
||||
Text(
|
||||
str("jit.recompiler.warning"),
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier.padding(bottom = 8.dp),
|
||||
)
|
||||
ToggleRow("EE (R5900)", settings.recEE) { apply(settings.copy(recEE = it)) }
|
||||
ToggleRow("IOP (R3000)", settings.recIOP) { apply(settings.copy(recIOP = it)) }
|
||||
ToggleRow("VU0", settings.recVU0) { apply(settings.copy(recVU0 = it)) }
|
||||
ToggleRow("VU1", settings.recVU1) { apply(settings.copy(recVU1 = it)) }
|
||||
ToggleRow("Fastmem", settings.enableFastmem) { apply(settings.copy(enableFastmem = it)) }
|
||||
|
||||
Spacer(Modifier.height(14.dp))
|
||||
Text(
|
||||
str("jit.diagnostics.header"),
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
modifier = Modifier.padding(horizontal = 4.dp, vertical = 4.dp),
|
||||
)
|
||||
// Seed from the REAL native flag. This was a plain `remember { false }`, so leaving the
|
||||
// screen destroyed the state and the switch came back showing OFF while the native flag
|
||||
// was still on — the toggle was reporting fiction.
|
||||
var eeDiff by remember {
|
||||
mutableStateOf(runCatching { NativeApp.isEeDiffVerify() }.getOrDefault(false))
|
||||
}
|
||||
ToggleRow(
|
||||
label = str("jit.eeDiffVerify.label"),
|
||||
value = eeDiff,
|
||||
description = str("jit.eeDiffVerify.description"),
|
||||
) {
|
||||
eeDiff = it
|
||||
runCatching { NativeApp.setEeDiffVerify(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,7 @@ fun RendererTab(state: MutableState<Settings>) {
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
) {
|
||||
CollapsibleSection(str("renderer.section.displayResolution"), initiallyExpanded = false) {
|
||||
CollapsibleSection(str("renderer.section.displayResolution"), initiallyExpanded = true) {
|
||||
// Graphics API (OpenGL / Vulkan) + Vulkan custom-driver picker.
|
||||
// from the removed first-run setup renderer page into settings.
|
||||
RendererBackendSection(state)
|
||||
|
||||
@@ -515,18 +515,37 @@ fun SettingsDivider() {
|
||||
/** Collapsible settings section: a tappable header (▸ collapsed / ▾ expanded) that
|
||||
* shows or hides its content. Controller-focusable so a gamepad can open it. Shared
|
||||
* by the Fixes / Pad / Performance / Renderer tabs to de-bloat long settings lists.
|
||||
* [initiallyExpanded] lets a tab open its most-used section by default. */
|
||||
* [initiallyExpanded] lets a tab open its most-used section by default.
|
||||
*
|
||||
* This is the de-bloating that the settings screens were built around, and it had stopped
|
||||
* happening: the header rendered as plain text and `content()` was called unconditionally, with
|
||||
* `initiallyExpanded` marked UNUSED_PARAMETER. Every tab was therefore one flat list of every
|
||||
* option it owns — the reason the settings became unusable in landscape. Restoring it shortens
|
||||
* Pad / Renderer / Performance / Advanced all at once.
|
||||
*
|
||||
* State is [rememberSaveable] so a rotation does not re-collapse what the user just opened —
|
||||
* landscape being exactly where the long lists hurt most. */
|
||||
@Composable
|
||||
fun CollapsibleSection(
|
||||
title: String,
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
initiallyExpanded: Boolean = false,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
var expanded by androidx.compose.runtime.saveable.rememberSaveable(title) {
|
||||
mutableStateOf(initiallyExpanded)
|
||||
}
|
||||
val toggle = {
|
||||
expanded = !expanded
|
||||
com.armsx2.MenuSfx.play(
|
||||
if (expanded) com.armsx2.MenuSfx.Event.TOGGLE_ON else com.armsx2.MenuSfx.Event.TOGGLE_OFF
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.height(12.dp))
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.controllerFocusable("section.$title", onConfirm = toggle)
|
||||
.clickable(onClick = toggle)
|
||||
.padding(horizontal = 8.dp, vertical = 10.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
@@ -537,8 +556,16 @@ fun CollapsibleSection(
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
Text(
|
||||
if (expanded) "▾" else "▸",
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
)
|
||||
}
|
||||
content()
|
||||
// Collapsed content is not composed at all, so its rows also drop out of the controller-focus
|
||||
// registry — a pad cannot land on a setting the user cannot see.
|
||||
if (expanded) content()
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
+11
-7
@@ -25,8 +25,8 @@ import org.json.JSONObject
|
||||
internal val SETTINGS_CATEGORY_FIELDS: Map<SettingsCategory, List<String>> = mapOf(
|
||||
// PerformanceTab.kt
|
||||
SettingsCategory.Performance to listOf(
|
||||
"eeClampMode", "eeCycleRate", "eeCycleSkip", "eeFpuRoundMode", "enableFastBoot",
|
||||
"enableGameFixes", "fastCDVD", "fpsLimit", "frameSkip", "framerateNtsc", "frameratePal",
|
||||
"eeClampMode", "eeCycleRate", "eeCycleSkip", "eeFpuRoundMode",
|
||||
"fastCDVD", "fpsLimit", "frameSkip", "framerateNtsc", "frameratePal",
|
||||
"intcStat", "mtvu", "nominalSpeedPercent", "skipDuplicateFrames", "vu0RoundMode",
|
||||
"vu1Instant", "vu1RoundMode", "vuClampMode", "vuDeferredWrites", "vuFlagHack",
|
||||
"vuNeonFusions", "vuSkipStallSim", "waitLoop",
|
||||
@@ -65,8 +65,16 @@ internal val SETTINGS_CATEGORY_FIELDS: Map<SettingsCategory, List<String>> = map
|
||||
"osdShowMessages", "osdShowResolution", "osdShowSettings", "osdShowSpeed",
|
||||
"osdShowVersion", "osdShowVps",
|
||||
),
|
||||
// FixesTab.kt
|
||||
// FixesTab.kt — also owns the GameDB fixes and the recompiler toggles, which moved here
|
||||
// from Performance and from the retired Recompiler tab.
|
||||
SettingsCategory.Advanced to listOf(
|
||||
"enableFastBoot", "enableGameFixes",
|
||||
"gamefixBlitInternalFps", "gamefixDmaBusy", "gamefixEETiming", "gamefixFpuMul",
|
||||
"gamefixFullVu0Sync", "gamefixGifFifo", "gamefixGoemonTlb", "gamefixIbit",
|
||||
"gamefixInstantDma", "gamefixOphFlag", "gamefixSkipMpeg",
|
||||
"gamefixSoftwareRendererFmv", "gamefixVif1Stall", "gamefixVuAddSub",
|
||||
"gamefixVuOverflow", "gamefixVuSync", "gamefixXgkick",
|
||||
"enableFastmem", "recEE", "recIOP", "recVU0", "recVU1",
|
||||
"alignSprite", "antiBlur", "autoFlush", "autoFlushSw", "bilinearUpscale", "cpuClutRender",
|
||||
"cpuFramebufferConversion", "cpuSpriteRenderBw", "cpuSpriteRenderLevel", "cropBottom",
|
||||
"cropLeft", "cropRight", "cropTop", "displayZoom", "disableDepthEmulation", "disableFramebufferFetch",
|
||||
@@ -81,10 +89,6 @@ internal val SETTINGS_CATEGORY_FIELDS: Map<SettingsCategory, List<String>> = map
|
||||
"syncToHostRefresh", "textureInsideRt", "textureOffsetX", "textureOffsetY",
|
||||
"unscaledPaletteDraw", "useBlitSwapChain", "vsyncQueueSize",
|
||||
),
|
||||
// RecompilerTab.kt
|
||||
SettingsCategory.Recompiler to listOf(
|
||||
"enableFastmem", "recEE", "recIOP", "recVU0", "recVU1",
|
||||
),
|
||||
// Controls / Hotkeys / Skins / General / Info / Patches / About own no Settings fields —
|
||||
// Controls keeps its binds and tunables in ControllerMappings and has its own reset row.
|
||||
)
|
||||
|
||||
@@ -67,7 +67,6 @@ import com.armsx2.ui.settings.NetworkTab
|
||||
import com.armsx2.ui.settings.OverlayTab
|
||||
import com.armsx2.ui.settings.PadTab
|
||||
import com.armsx2.ui.settings.PerformanceTab
|
||||
import com.armsx2.ui.settings.RecompilerTab
|
||||
import com.armsx2.ui.settings.RendererTab
|
||||
import com.armsx2.ui.settings.SegmentedRow
|
||||
import com.armsx2.ui.settings.SkinsTab
|
||||
@@ -338,7 +337,7 @@ private fun SettingsCategoryBar(
|
||||
) {
|
||||
// Row + horizontalScroll (NOT LazyRow): controllerFocusable registers each tab via a
|
||||
// SideEffect that only runs for COMPOSED children. A LazyRow leaves every off-screen
|
||||
// tab (Skins / Fixes / Recompiler, past On-Screen) unregistered and unreachable, so
|
||||
// tab (Skins / Advanced, past On-Screen) unregistered and unreachable, so
|
||||
// the controller got stuck at the last visible tab. A plain Row composes them all;
|
||||
// each selected chip's bringIntoView then scrolls it into view as the selector moves.
|
||||
val sections = settingsSections().filterNot {
|
||||
@@ -417,9 +416,7 @@ private fun settingsSections() = listOf(
|
||||
SettingsSection(SettingsCategory.OnScreen, "tab.overlay", "⊕"),
|
||||
SettingsSection(SettingsCategory.Skins, "tab.skins", "◈"),
|
||||
SettingsSection(SettingsCategory.Advanced, "tab.fixes", "⌘"),
|
||||
SettingsSection(SettingsCategory.Recompiler, "tab.recompiler", "⚙"),
|
||||
SettingsSection(SettingsCategory.Patches, "tab.patches", "✦"),
|
||||
SettingsSection(SettingsCategory.About, "about.title", "ⓘ"),
|
||||
)
|
||||
|
||||
@Composable
|
||||
@@ -436,7 +433,6 @@ private fun CategoryContent(category: SettingsCategory, viewModel: SettingsViewM
|
||||
SettingsCategory.OnScreen -> OverlayTab(viewModel.settings)
|
||||
SettingsCategory.Skins -> SkinsTab(viewModel.settings)
|
||||
SettingsCategory.Advanced -> FixesTab(viewModel.settings)
|
||||
SettingsCategory.Recompiler -> RecompilerTab(viewModel.settings)
|
||||
SettingsCategory.Patches -> com.armsx2.ui.patches.PatchesSettingsTab(viewModel.uiState.value.game)
|
||||
SettingsCategory.About -> Unit
|
||||
}
|
||||
@@ -455,7 +451,6 @@ internal fun categoryTitle(category: SettingsCategory): String = when (category)
|
||||
SettingsCategory.OnScreen -> str("tab.overlay")
|
||||
SettingsCategory.Skins -> str("tab.skins")
|
||||
SettingsCategory.Advanced -> str("tab.fixes")
|
||||
SettingsCategory.Recompiler -> str("tab.recompiler")
|
||||
SettingsCategory.Patches -> str("patches.dialog.patchesAndCheats")
|
||||
SettingsCategory.About -> str("about.title")
|
||||
}
|
||||
|
||||
+27
-26
@@ -17,6 +17,7 @@ internal val SETTINGS_SEARCH_INDEX: List<SettingsSearchEntry> = listOf(
|
||||
SettingsSearchEntry("app.library.search", true, SettingsCategory.General),
|
||||
SettingsSearchEntry("app.library.recents", true, SettingsCategory.General),
|
||||
SettingsSearchEntry("app.library.coverSize", true, SettingsCategory.General),
|
||||
SettingsSearchEntry("games.overflow.gridNames", true, SettingsCategory.General),
|
||||
SettingsSearchEntry("app.backup.export", true, SettingsCategory.General),
|
||||
SettingsSearchEntry("app.backup.import", true, SettingsCategory.General),
|
||||
SettingsSearchEntry("app.blockHome", true, SettingsCategory.General),
|
||||
@@ -26,25 +27,25 @@ internal val SETTINGS_SEARCH_INDEX: List<SettingsSearchEntry> = listOf(
|
||||
SettingsSearchEntry("app.bgColor", true, SettingsCategory.General),
|
||||
SettingsSearchEntry("app.menuSfx", true, SettingsCategory.General),
|
||||
SettingsSearchEntry("update.includeNightly", true, SettingsCategory.General),
|
||||
SettingsSearchEntry("perf.fix.skipBios", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.gamedbFixes", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.skipMpeg", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.fmvSoftware", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.eeTiming", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.instantDma", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.blitFps", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.fpuMultiply", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.ophFlag", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.gifFifo", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.dmaBusy", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.vif1Stall", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.iBit", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.fullVu0Sync", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.vuAddSub", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.vuOverflow", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.extraXgkick", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.goemonTlb", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.vuSync", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.fix.skipBios", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.gamedbFixes", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.skipMpeg", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.fmvSoftware", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.eeTiming", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.instantDma", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.blitFps", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.fpuMultiply", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.ophFlag", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.gifFifo", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.dmaBusy", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.vif1Stall", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.iBit", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.fullVu0Sync", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.vuAddSub", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.vuOverflow", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.extraXgkick", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.goemonTlb", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.fix.vuSync", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.hack.mtvu", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.hack.instantVu1", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.hack.vuFlagHack", true, SettingsCategory.Performance),
|
||||
@@ -74,7 +75,7 @@ internal val SETTINGS_SEARCH_INDEX: List<SettingsSearchEntry> = listOf(
|
||||
SettingsSearchEntry("perf.vu0RoundMode.label", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.vu1RoundMode.label", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.speedhacks.title", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.gamedbFixes.title", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("perf.gamedbFixes.title", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("perf.advancedSpeedhacks.title", true, SettingsCategory.Performance),
|
||||
SettingsSearchEntry("VSync", false, SettingsCategory.Graphics),
|
||||
SettingsSearchEntry("renderer.shadeboost.label", true, SettingsCategory.Graphics),
|
||||
@@ -248,12 +249,12 @@ internal val SETTINGS_SEARCH_INDEX: List<SettingsSearchEntry> = listOf(
|
||||
SettingsSearchEntry("fixes.section.upscaling", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("fixes.section.hardware", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("fixes.section.software", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("EE (R5900)", false, SettingsCategory.Recompiler),
|
||||
SettingsSearchEntry("IOP (R3000)", false, SettingsCategory.Recompiler),
|
||||
SettingsSearchEntry("VU0", false, SettingsCategory.Recompiler),
|
||||
SettingsSearchEntry("VU1", false, SettingsCategory.Recompiler),
|
||||
SettingsSearchEntry("Fastmem", false, SettingsCategory.Recompiler),
|
||||
SettingsSearchEntry("jit.eeDiffVerify.label", true, SettingsCategory.Recompiler),
|
||||
SettingsSearchEntry("EE (R5900)", false, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("IOP (R3000)", false, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("VU0", false, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("VU1", false, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("Fastmem", false, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("jit.eeDiffVerify.label", true, SettingsCategory.Advanced),
|
||||
SettingsSearchEntry("patches.enablePatches.label", true, SettingsCategory.Patches),
|
||||
SettingsSearchEntry("patches.cheats.label", true, SettingsCategory.Patches),
|
||||
SettingsSearchEntry("patches.widescreen.label", true, SettingsCategory.Patches),
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<!-- Tabler Icons (MIT) - power. Standard IEC power symbol: a broken ring with a vertical bar.
|
||||
Replaces the "⏻" text glyph, which most Android system fonts do not carry and which therefore
|
||||
rendered as a tofu box in the drawer. Stroke-based like ic_discord/ic_github; tinted red at the
|
||||
call site since Exit is the one destructive row in the drawer. -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#FFFFFFFF">
|
||||
<path
|
||||
android:strokeColor="#FFFFFFFF"
|
||||
android:strokeWidth="2"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round"
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M7 6a7.75 7.75 0 1 0 10 0" />
|
||||
<path
|
||||
android:strokeColor="#FFFFFFFF"
|
||||
android:strokeWidth="2"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round"
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M12 4l0 8" />
|
||||
</vector>
|
||||
Reference in New Issue
Block a user