Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class GameMenuActivity : RetrogradeComponentActivity() {
val coreConfig: SystemCoreConfig,
val audioEnabled: Boolean,
val fastForwardSupported: Boolean,
val fastForwardEnabled: Boolean,
val frameSpeed: Int,
val numDisks: Int,
val currentDisk: Int,
val currentTiltConfiguration: TiltConfiguration,
Expand All @@ -93,6 +93,12 @@ class GameMenuActivity : RetrogradeComponentActivity() {
)

val extras = intent.extras
val legacyFastForwardEnabled = extras?.getBoolean(GameMenuContract.EXTRA_FAST_FORWARD, false) ?: false
val frameSpeed =
extras?.getInt(
GameMenuContract.EXTRA_FRAME_SPEED,
if (legacyFastForwardEnabled) 2 else 1,
) ?: 1

val gameMenuRequest =
GameMenuRequest(
Expand All @@ -114,8 +120,7 @@ class GameMenuActivity : RetrogradeComponentActivity() {
extras?.getBoolean(GameMenuContract.EXTRA_AUDIO_ENABLED, false) ?: false,
fastForwardSupported =
extras?.getBoolean(GameMenuContract.EXTRA_FAST_FORWARD_SUPPORTED, false) ?: false,
fastForwardEnabled =
extras?.getBoolean(GameMenuContract.EXTRA_FAST_FORWARD, false) ?: false,
frameSpeed = frameSpeed,
numDisks =
extras?.getInt(GameMenuContract.EXTRA_DISKS, 0) ?: 0,
currentDisk =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavController
import com.alorma.compose.settings.storage.memory.rememberMemoryBooleanSettingState
Expand Down Expand Up @@ -95,17 +96,39 @@ fun GameMenuHomeScreen(
)

if (gameMenuRequest.fastForwardSupported) {
LemuroidSettingsSwitch(
val speedLabels = stringArrayResource(R.array.game_menu_fast_forward_speeds).toList()
val speedValues =
stringArrayResource(R.array.game_menu_fast_forward_speed_values)
.map { it.toInt() }

val selectedIndex =
speedValues.indexOf(gameMenuRequest.frameSpeed).let { if (it >= 0) it else 0 }

LemuroidSettingsList(
title = { Text(text = stringResource(id = R.string.game_menu_fast_forward)) },
items = speedLabels,
useSelectedValueAsSubtitle = false,
subtitle = {
Text(
text =
speedLabels[selectedIndex] +
" - " +
stringResource(R.string.game_menu_fast_forward_note),
)
},
icon = {
Icon(
painterResource(R.drawable.ic_menu_fast_forward),
contentDescription = stringResource(id = R.string.game_menu_fast_forward),
)
},
state = rememberMemoryBooleanSettingState(gameMenuRequest.fastForwardEnabled),
onCheckedChange = {
onResult { putExtra(GameMenuContract.RESULT_ENABLE_FAST_FORWARD, it) }
state = rememberMemoryIntSettingState(selectedIndex),
onItemSelected = { index, _ ->
val speed = speedValues[index]
onResult {
putExtra(GameMenuContract.RESULT_SET_FRAME_SPEED, speed)
putExtra(GameMenuContract.RESULT_ENABLE_FAST_FORWARD, speed > 1)
}
},
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource
import com.swordfish.lemuroid.R
import com.swordfish.lemuroid.app.mobile.feature.input.GamePadBindingActivity
Expand All @@ -18,12 +19,13 @@ import com.swordfish.lemuroid.app.shared.input.InputBindingUpdater
import com.swordfish.lemuroid.app.shared.input.InputKey
import com.swordfish.lemuroid.app.shared.input.ShortcutBindingUpdater
import com.swordfish.lemuroid.app.shared.input.lemuroiddevice.getLemuroidInputDevice
import com.swordfish.lemuroid.app.shared.settings.GameShortcut
import com.swordfish.lemuroid.app.utils.android.settings.LemuroidCardSettingsGroup
import com.swordfish.lemuroid.app.utils.android.settings.LemuroidSettingsMenuLink
import com.swordfish.lemuroid.app.utils.android.settings.LemuroidSettingsPage
import com.swordfish.lemuroid.app.utils.android.settings.LemuroidSettingsSwitch
import com.swordfish.lemuroid.app.utils.android.settings.booleanPreferenceState
import com.swordfish.lemuroid.app.utils.android.settings.LemuroidSettingsListMultiSelect
import com.swordfish.lemuroid.app.utils.android.settings.stringsSetPreferenceState

@Composable
fun InputDevicesSettingsScreen(
Expand Down Expand Up @@ -80,11 +82,12 @@ private fun DeviceBindingCategory(
private fun DeviceShortcutBinding(
context: Context,
device: InputDevice,
shortcut: GameShortcut,
shortcut: InputDevicesSettingsViewModel.ShortcutView,
) {
val subtitleText = shortcut.shortcut?.name ?: stringResource(R.string.shortcut_not_set)
LemuroidSettingsMenuLink(
title = { Text(text = shortcut.type.displayName()) },
subtitle = { Text(text = shortcut.name) },
subtitle = { Text(text = subtitleText) },
onClick = {
val intent =
Intent(context, GamePadShortcutBindingActivity::class.java).apply {
Expand All @@ -111,6 +114,30 @@ private fun EnabledDeviceCategory(state: InputDevicesSettingsViewModel.State) {
@Composable
private fun GeneralOptionsCategory(viewModel: InputDevicesSettingsViewModel) {
LemuroidCardSettingsGroup(title = { Text(text = stringResource(R.string.settings_gamepad_category_general)) }) {
val speedLabels = stringArrayResource(R.array.game_menu_fast_forward_speeds).toList()
val speedValues = stringArrayResource(R.array.game_menu_fast_forward_speed_values).toList()
val cycleKey = stringResource(R.string.pref_key_fast_forward_cycle_speeds)
val defaultCycle = speedValues.toSet()
val cycleState = stringsSetPreferenceState(key = cycleKey, default = defaultCycle)

LemuroidSettingsListMultiSelect(
title = { Text(text = stringResource(R.string.settings_fast_forward_cycle_title)) },
subtitle = { Text(text = stringResource(R.string.settings_fast_forward_cycle_subtitle)) },
entries = speedLabels,
entryValues = speedValues,
confirmButton = stringResource(R.string.settings_fast_forward_cycle_confirm),
state = cycleState,
onItemsSelected = { selectedValues ->
val mutable = selectedValues.toMutableSet()
mutable.add("1")
if (mutable.size == 1) {
mutable.add("2")
}
val enforced = mutable.toSet()
cycleState.value = enforced
},
)

LemuroidSettingsMenuLink(
title = { Text(text = stringResource(R.string.settings_gamepad_title_reset_bindings)) },
onClick = { viewModel.resetAllBindings() },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.swordfish.lemuroid.app.shared.input.InputKey
import com.swordfish.lemuroid.app.shared.input.RetroKey
import com.swordfish.lemuroid.app.shared.input.lemuroiddevice.getLemuroidInputDevice
import com.swordfish.lemuroid.app.shared.settings.GameShortcut
import com.swordfish.lemuroid.app.shared.settings.GameShortcutType
import com.swordfish.lemuroid.common.kotlin.reverseLookup
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
Expand Down Expand Up @@ -39,7 +40,12 @@ class InputDevicesSettingsViewModel(

data class BindingsView(
val keys: Map<RetroKey, InputKey> = emptyMap(),
val shortcuts: List<GameShortcut> = emptyList(),
val shortcuts: List<ShortcutView> = emptyList(),
)

data class ShortcutView(
val type: GameShortcutType,
val shortcut: GameShortcut?,
)

data class State(
Expand Down Expand Up @@ -86,10 +92,16 @@ class InputDevicesSettingsViewModel(

return combine(devicesFlow, bindingsFlow, shortcutsFlow) { devices, allBindings, allShortcuts ->
devices.associateWith { device ->
val supportedShortcutTypes = device.getLemuroidInputDevice().getSupportedShortcuts()
val configuredShortcutsByType = (allShortcuts[device] ?: emptyList()).associateBy { it.type }

val shortcuts =
allShortcuts[device]?.filter {
it.type in device.getLemuroidInputDevice().getSupportedShortcuts()
} ?: emptyList()
supportedShortcutTypes.map { type ->
ShortcutView(
type = type,
shortcut = configuredShortcutsByType[type],
)
}
val keys = allBindings(device).reverseLookup()

BindingsView(keys, shortcuts)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ object GameMenuContract {
const val EXTRA_AUDIO_ENABLED = "EXTRA_AUDIO_ENABLED"
const val EXTRA_FAST_FORWARD_SUPPORTED = "EXTRA_FAST_FORWARD_SUPPORTED"
const val EXTRA_FAST_FORWARD = "EXTRA_FAST_FORWARD"
const val EXTRA_FRAME_SPEED = "EXTRA_FRAME_SPEED"
const val EXTRA_CURRENT_TILT_CONFIG = "EXTRA_CURRENT_TILT_CONFIG"
const val EXTRA_TILT_ALL_CONFIGS = "EXTRA_TILT_ALL_CONFIGS"

Expand All @@ -21,5 +22,6 @@ object GameMenuContract {
const val RESULT_EDIT_TOUCH_CONTROLS = "RESULT_EDIT_TOUCH_CONTROLS"
const val RESULT_ENABLE_AUDIO = "RESULT_ENABLE_AUDIO"
const val RESULT_ENABLE_FAST_FORWARD = "RESULT_ENABLE_FAST_FORWARD"
const val RESULT_SET_FRAME_SPEED = "RESULT_SET_FRAME_SPEED"
const val RESULT_CHANGE_TILT_CONFIG = "RESULT_CHANGE_TILT_CONFIG"
}
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ abstract class BaseGameActivity : ImmersiveActivity() {

val intent =
Intent(this, getDialogClass()).apply {
val currentFrameSpeed = baseGameScreenViewModel.retroGameView.retroGameView?.frameSpeed ?: 1
this.putExtra(GameMenuContract.EXTRA_CORE_OPTIONS, options.toTypedArray())
this.putExtra(GameMenuContract.EXTRA_ADVANCED_CORE_OPTIONS, advancedOptions.toTypedArray())
this.putExtra(
Expand All @@ -210,9 +211,10 @@ abstract class BaseGameActivity : ImmersiveActivity() {
baseGameScreenViewModel.retroGameView.retroGameView?.audioEnabled,
)
this.putExtra(GameMenuContract.EXTRA_FAST_FORWARD_SUPPORTED, system.fastForwardSupport)
this.putExtra(GameMenuContract.EXTRA_FRAME_SPEED, currentFrameSpeed)
this.putExtra(
GameMenuContract.EXTRA_FAST_FORWARD,
(baseGameScreenViewModel.retroGameView.retroGameView?.frameSpeed ?: 1) > 1,
currentFrameSpeed > 1,
)
this.putExtra(GameMenuContract.EXTRA_CURRENT_TILT_CONFIG, currentTiltConfiguration)
// TODO PADS... Make sure to avoid passing this if a physical pad is connected.
Expand Down Expand Up @@ -396,7 +398,18 @@ abstract class BaseGameActivity : ImmersiveActivity() {
)
}
}
if (data?.hasExtra(GameMenuContract.RESULT_ENABLE_FAST_FORWARD) == true) {
val hasFrameSpeed = data?.hasExtra(GameMenuContract.RESULT_SET_FRAME_SPEED) == true
if (hasFrameSpeed) {
baseGameScreenViewModel.retroGameView.retroGameView?.apply {
val frameSpeed =
data.getIntExtra(
GameMenuContract.RESULT_SET_FRAME_SPEED,
1,
)
this.frameSpeed = frameSpeed
}
}
if (!hasFrameSpeed && data?.hasExtra(GameMenuContract.RESULT_ENABLE_FAST_FORWARD) == true) {
baseGameScreenViewModel.retroGameView.retroGameView?.apply {
val fastForwardEnabled =
data.getBooleanExtra(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.swordfish.lemuroid.app.shared.rumble.RumbleManager
import com.swordfish.lemuroid.app.shared.settings.ControllerConfigsManager
import com.swordfish.lemuroid.app.shared.settings.HapticFeedbackMode
import com.swordfish.lemuroid.common.longAnimationDuration
import com.swordfish.lemuroid.R
import com.swordfish.lemuroid.lib.controller.ControllerConfig
import com.swordfish.lemuroid.lib.core.CoreVariablesManager
import com.swordfish.lemuroid.lib.game.GameLoader
Expand Down Expand Up @@ -52,7 +53,7 @@ class BaseGameScreenViewModel(
controllerConfigsManager: ControllerConfigsManager,
system: GameSystem,
systemCoreConfig: SystemCoreConfig,
sharedPreferences: SharedPreferences,
private val sharedPreferences: SharedPreferences,
savesManager: SavesManager,
statesManager: StatesManager,
statesPreviewManager: StatesPreviewManager,
Expand Down Expand Up @@ -270,10 +271,42 @@ class BaseGameScreenViewModel(
fun toggleFastForward() {
Timber.d("Loading quick save")
retroGameView.retroGameView?.apply {
frameSpeed = if (frameSpeed == 1) 2 else 1
val speeds = getFastForwardCycleSpeeds()
val currentIndex = speeds.indexOf(frameSpeed).let { if (it >= 0) it else 0 }
frameSpeed = speeds[(currentIndex + 1) % speeds.size]
}
}

private fun getFastForwardCycleSpeeds(): List<Int> {
val key = appContext.getString(R.string.pref_key_fast_forward_cycle_speeds)
val raw =
sharedPreferences.getStringSet(
key,
DEFAULT_FAST_FORWARD_CYCLE_SPEEDS.map { it.toString() }.toSet(),
) ?: emptySet()

val parsed =
raw.mapNotNull { it.toIntOrNull() }
.filter { it >= 1 }
.distinct()
.sorted()
.toMutableList()

if (parsed.isEmpty()) {
return DEFAULT_FAST_FORWARD_CYCLE_SPEEDS
}

if (!parsed.contains(1)) {
parsed.add(0, 1)
}

return parsed
}

companion object {
private val DEFAULT_FAST_FORWARD_CYCLE_SPEEDS = listOf(1, 2, 4, 8, 16)
}

suspend fun reset() =
withLoading {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,38 @@ object GameMenuHelper {
}

fun setupFastForwardOption(
activity: Activity?,
screen: PreferenceScreen,
fastForwardEnabled: Boolean,
frameSpeed: Int,
fastForwardSupported: Boolean,
) {
val preference = screen.findPreference<SwitchPreference>(FAST_FORWARD)
preference?.isChecked = fastForwardEnabled
val preference = screen.findPreference<ListPreference>(FAST_FORWARD)
preference?.isVisible = fastForwardSupported

val speedLabels = screen.context.resources.getStringArray(R.array.game_menu_fast_forward_speeds)
val speedValues = screen.context.resources.getStringArray(R.array.game_menu_fast_forward_speed_values)

preference?.entries = speedLabels
preference?.entryValues = speedValues

val selectedIndex =
speedValues.indexOf(frameSpeed.toString()).let { if (it >= 0) it else 0 }

preference?.setValueIndex(selectedIndex)
preference?.summary =
(speedLabels.getOrNull(selectedIndex) ?: "") +
" - " +
screen.context.getString(R.string.game_menu_fast_forward_note)
preference?.setOnPreferenceChangeListener { _, newValue ->
val speed = (newValue as? String)?.toIntOrNull() ?: 1
val resultIntent =
Intent().apply {
putExtra(GameMenuContract.RESULT_SET_FRAME_SPEED, speed)
putExtra(GameMenuContract.RESULT_ENABLE_FAST_FORWARD, speed > 1)
}
setResultAndFinish(activity, resultIntent)
true
}
}

fun setupSaveOption(
Expand Down Expand Up @@ -152,15 +177,6 @@ object GameMenuHelper {
setResultAndFinish(activity, resultIntent)
true
}
"pref_game_fast_forward" -> {
val currentValue = (preference as SwitchPreference).isChecked
val resultIntent =
Intent().apply {
putExtra(GameMenuContract.RESULT_ENABLE_FAST_FORWARD, currentValue)
}
setResultAndFinish(activity, resultIntent)
true
}
"pref_game_reset" -> {
val resultIntent =
Intent().apply {
Expand Down
Loading