[frontend] Slow and Turbo modes (#3525)
Closes #3344 Adds slow and turbo modes with configurable speeds that can then be toggled by the user. Behavior is: - Standard/slow limit, toggle turbo = turbo - Turbo limit, toggle turbo = standard - Standard/turbo limit, toggle slow = slow - Slow limit, toggle slow = standard Enabling the turbo/slow mode enables the frame limiter unconditionally. This has some conflicts with VSync. For example when I set my refresh rate to 60hz and enable vsync, turbo mode does nothing. Not sure how to go about fixing this, @MaranBr probably knows better the proper solution. Signed-off-by: crueter <crueter@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3525 Reviewed-by: DraVee <dravee@eden-emu.dev> Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
This commit is contained in:
parent
5f676a6a55
commit
2b979024cb
|
|
@ -203,6 +203,24 @@ object NativeLibrary {
|
|||
|
||||
external fun getDebugKnobAt(index: Int): Boolean
|
||||
|
||||
/**
|
||||
* Set the current speed limit to the configured turbo speed.
|
||||
*/
|
||||
external fun setTurboSpeedLimit(enabled: Boolean)
|
||||
|
||||
/**
|
||||
* Set the current speed limit to the configured slow speed.
|
||||
*/
|
||||
external fun setSlowSpeedLimit(enabled: Boolean)
|
||||
|
||||
/**
|
||||
* Set the current speed limit to the configured standard speed.
|
||||
*/
|
||||
external fun setStandardSpeedLimit(enabled: Boolean)
|
||||
|
||||
external fun isTurboMode(): Boolean
|
||||
external fun isSlowMode(): Boolean
|
||||
|
||||
/**
|
||||
* Returns Vulkan driver version / API version / GPU model
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import android.widget.RadioGroup
|
|||
import android.widget.TextView
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.materialswitch.MaterialSwitch
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
||||
|
|
@ -135,6 +136,39 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
|||
container.addView(itemView)
|
||||
}
|
||||
|
||||
fun addCustomToggle(
|
||||
name: Int,
|
||||
isChecked: Boolean,
|
||||
isEnabled: Boolean,
|
||||
|
||||
container: ViewGroup,
|
||||
callback: (Boolean) -> Unit
|
||||
): MaterialSwitch? {
|
||||
val inflater = LayoutInflater.from(emulationFragment.requireContext())
|
||||
val itemView = inflater.inflate(R.layout.item_quick_settings_menu, container, false)
|
||||
|
||||
val switchContainer = itemView.findViewById<ViewGroup>(R.id.switch_container)
|
||||
val titleView = itemView.findViewById<TextView>(R.id.switch_title)
|
||||
val switchView = itemView.findViewById<MaterialSwitch>(R.id.setting_switch)
|
||||
|
||||
titleView.text = YuzuApplication.appContext.getString(name)
|
||||
switchContainer.visibility = View.VISIBLE
|
||||
|
||||
switchView.isChecked = isChecked
|
||||
|
||||
switchView.setOnCheckedChangeListener { _, checked ->
|
||||
callback(checked)
|
||||
saveSettings()
|
||||
}
|
||||
|
||||
switchContainer.setOnClickListener {
|
||||
switchView.toggle()
|
||||
}
|
||||
container.addView(itemView)
|
||||
|
||||
return switchView
|
||||
}
|
||||
|
||||
fun addSliderSetting(
|
||||
name: Int,
|
||||
container: ViewGroup,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -6,7 +9,10 @@ package org.yuzu.yuzu_emu.features.settings.model
|
|||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||
|
||||
enum class ShortSetting(override val key: String) : AbstractShortSetting {
|
||||
RENDERER_SPEED_LIMIT("speed_limit");
|
||||
RENDERER_SPEED_LIMIT("speed_limit"),
|
||||
RENDERER_TURBO_SPEED_LIMIT("turbo_speed_limit"),
|
||||
RENDERER_SLOW_SPEED_LIMIT("slow_speed_limit"),
|
||||
;
|
||||
|
||||
override fun getShort(needsGlobal: Boolean): Short = NativeConfig.getShort(key, needsGlobal)
|
||||
|
||||
|
|
|
|||
|
|
@ -180,6 +180,26 @@ abstract class SettingsItem(
|
|||
units = "%"
|
||||
)
|
||||
)
|
||||
put(
|
||||
SliderSetting(
|
||||
ShortSetting.RENDERER_TURBO_SPEED_LIMIT,
|
||||
titleId = R.string.turbo_speed_limit,
|
||||
descriptionId = R.string.turbo_speed_limit_description,
|
||||
min = 1,
|
||||
max = 400,
|
||||
units = "%"
|
||||
)
|
||||
)
|
||||
put(
|
||||
SliderSetting(
|
||||
ShortSetting.RENDERER_SLOW_SPEED_LIMIT,
|
||||
titleId = R.string.slow_speed_limit,
|
||||
descriptionId = R.string.slow_speed_limit_description,
|
||||
min = 1,
|
||||
max = 400,
|
||||
units = "%"
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.CPU_BACKEND,
|
||||
|
|
|
|||
|
|
@ -227,6 +227,8 @@ class SettingsFragmentPresenter(
|
|||
add(StringSetting.DEVICE_NAME.key)
|
||||
add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key)
|
||||
add(ShortSetting.RENDERER_SPEED_LIMIT.key)
|
||||
add(ShortSetting.RENDERER_TURBO_SPEED_LIMIT.key)
|
||||
add(ShortSetting.RENDERER_SLOW_SPEED_LIMIT.key)
|
||||
add(BooleanSetting.USE_DOCKED_MODE.key)
|
||||
add(IntSetting.REGION_INDEX.key)
|
||||
add(IntSetting.LANGUAGE_INDEX.key)
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ import androidx.window.layout.WindowInfoTracker
|
|||
import androidx.window.layout.WindowLayoutInfo
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.materialswitch.MaterialSwitch
|
||||
import com.google.android.material.textview.MaterialTextView
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -1055,11 +1056,47 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
quickSettings.addPerGameConfigStatusIndicator(container)
|
||||
}
|
||||
|
||||
quickSettings.addBooleanSetting(
|
||||
lateinit var slowSpeed: MaterialSwitch
|
||||
lateinit var turboSpeed: MaterialSwitch
|
||||
|
||||
turboSpeed = quickSettings.addCustomToggle(
|
||||
R.string.turbo_speed_limit,
|
||||
NativeLibrary.isTurboMode(),
|
||||
BooleanSetting.RENDERER_USE_SPEED_LIMIT.getBoolean(false),
|
||||
container
|
||||
) { enabled ->
|
||||
if (enabled)
|
||||
slowSpeed.isChecked = false
|
||||
NativeLibrary.setTurboSpeedLimit(enabled)
|
||||
}!!
|
||||
|
||||
slowSpeed = quickSettings.addCustomToggle(
|
||||
R.string.slow_speed_limit,
|
||||
NativeLibrary.isSlowMode(),
|
||||
BooleanSetting.RENDERER_USE_SPEED_LIMIT.getBoolean(false),
|
||||
container
|
||||
) { enabled ->
|
||||
if (enabled)
|
||||
turboSpeed.isChecked = false
|
||||
NativeLibrary.setSlowSpeedLimit(enabled)
|
||||
}!!
|
||||
|
||||
quickSettings.addCustomToggle(
|
||||
R.string.frame_limit_enable,
|
||||
container,
|
||||
BooleanSetting.RENDERER_USE_SPEED_LIMIT,
|
||||
)
|
||||
BooleanSetting.RENDERER_USE_SPEED_LIMIT.getBoolean(false),
|
||||
true,
|
||||
container
|
||||
) { enabled ->
|
||||
if (!enabled) {
|
||||
turboSpeed.isChecked = false
|
||||
slowSpeed.isChecked = false
|
||||
}
|
||||
|
||||
turboSpeed.isEnabled = enabled
|
||||
slowSpeed.isEnabled = enabled
|
||||
|
||||
NativeLibrary.setStandardSpeedLimit(enabled)
|
||||
}!!
|
||||
|
||||
quickSettings.addSliderSetting(
|
||||
R.string.frame_limit_slider,
|
||||
|
|
|
|||
|
|
@ -1233,6 +1233,39 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_getDebugKnobAt(JNIEnv* env, jobje
|
|||
return static_cast<jboolean>(Settings::getDebugKnobAt(static_cast<u8>(index)));
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setTurboSpeedLimit(JNIEnv *env, jobject jobj, jboolean enabled) {
|
||||
if (enabled) {
|
||||
Settings::values.use_speed_limit.SetValue(true);
|
||||
Settings::SetSpeedMode(Settings::SpeedMode::Turbo);
|
||||
} else {
|
||||
Settings::SetSpeedMode(Settings::SpeedMode::Standard);
|
||||
}
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setSlowSpeedLimit(JNIEnv *env, jobject jobj, jboolean enabled) {
|
||||
if (enabled) {
|
||||
Settings::values.use_speed_limit.SetValue(true);
|
||||
Settings::SetSpeedMode(Settings::SpeedMode::Slow);
|
||||
} else {
|
||||
Settings::SetSpeedMode(Settings::SpeedMode::Standard);
|
||||
}
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setStandardSpeedLimit(JNIEnv *env, jobject jobj, jboolean enabled) {
|
||||
Settings::values.use_speed_limit.SetValue(enabled);
|
||||
if (enabled) {
|
||||
Settings::SetSpeedMode(Settings::SpeedMode::Standard);
|
||||
}
|
||||
}
|
||||
|
||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isTurboMode(JNIEnv *env, jobject jobj) {
|
||||
return Settings::values.current_speed_mode.GetValue() == Settings::SpeedMode::Turbo;
|
||||
}
|
||||
|
||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isSlowMode(JNIEnv *env, jobject jobj) {
|
||||
return Settings::values.current_speed_mode.GetValue() == Settings::SpeedMode::Slow;
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
|
||||
jint j_program_index,
|
||||
jboolean j_frontend_initiated) {
|
||||
|
|
|
|||
|
|
@ -422,6 +422,10 @@
|
|||
<string name="frame_limit_enable_description">Limits emulation speed to a specified percentage of normal speed.</string>
|
||||
<string name="frame_limit_slider">Limit speed percent</string>
|
||||
<string name="frame_limit_slider_description">Specifies the percentage to limit emulation speed. 100% is the normal speed. Values higher or lower will increase or decrease the speed limit.</string>
|
||||
<string name="turbo_speed_limit">Turbo speed</string>
|
||||
<string name="turbo_speed_limit_description">When Turbo Mode is enabled, emulation will run at this speed.</string>
|
||||
<string name="slow_speed_limit">Slow speed</string>
|
||||
<string name="slow_speed_limit_description">When Slow Mode is enabled, emulation will run at this speed.</string>
|
||||
<string name="cpu_backend">CPU backend</string>
|
||||
<string name="cpu_accuracy">CPU accuracy</string>
|
||||
<string name="value_with_units">%1$s%2$s</string>
|
||||
|
|
|
|||
|
|
@ -379,4 +379,52 @@ void SetConfiguringGlobal(bool is_global) {
|
|||
configuring_global = is_global;
|
||||
}
|
||||
|
||||
u16 SpeedLimit() {
|
||||
switch (SpeedMode(values.current_speed_mode)) {
|
||||
case SpeedMode::Standard:
|
||||
return values.speed_limit.GetValue();
|
||||
case SpeedMode::Turbo:
|
||||
return values.turbo_speed_limit.GetValue();
|
||||
case SpeedMode::Slow:
|
||||
return values.slow_speed_limit.GetValue();
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
return 100;
|
||||
}
|
||||
|
||||
void SetSpeedMode(const SpeedMode& mode) {
|
||||
values.current_speed_mode.SetValue(mode);
|
||||
|
||||
switch (mode) {
|
||||
case SpeedMode::Turbo:
|
||||
case SpeedMode::Slow:
|
||||
values.use_speed_limit.SetValue(true);
|
||||
break;
|
||||
case SpeedMode::Standard:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleStandardMode() {
|
||||
values.use_speed_limit.SetValue(!values.use_speed_limit.GetValue());
|
||||
SetSpeedMode(SpeedMode::Standard);
|
||||
}
|
||||
|
||||
void ToggleTurboMode() {
|
||||
if (values.current_speed_mode.GetValue() != SpeedMode::Turbo)
|
||||
SetSpeedMode(SpeedMode::Turbo);
|
||||
else
|
||||
SetSpeedMode(SpeedMode::Standard);
|
||||
}
|
||||
|
||||
void ToggleSlowMode() {
|
||||
if (values.current_speed_mode.GetValue() != SpeedMode::Slow)
|
||||
SetSpeedMode(SpeedMode::Slow);
|
||||
else
|
||||
SetSpeedMode(SpeedMode::Standard);
|
||||
}
|
||||
|
||||
} // namespace Settings
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ struct Values {
|
|||
true};
|
||||
SwitchableSetting<bool> use_speed_limit{
|
||||
linkage, true, "use_speed_limit", Category::Core, Specialization::Paired, true, true};
|
||||
|
||||
SwitchableSetting<u16, true> speed_limit{linkage,
|
||||
100,
|
||||
0,
|
||||
|
|
@ -214,6 +215,30 @@ struct Values {
|
|||
true,
|
||||
true,
|
||||
&use_speed_limit};
|
||||
|
||||
SwitchableSetting<u16, true> slow_speed_limit{linkage,
|
||||
50,
|
||||
0,
|
||||
9999,
|
||||
"slow_speed_limit",
|
||||
Category::Core,
|
||||
Specialization::Countable | Specialization::Percentage,
|
||||
true,
|
||||
true};
|
||||
|
||||
SwitchableSetting<u16, true> turbo_speed_limit{linkage,
|
||||
200,
|
||||
0,
|
||||
9999,
|
||||
"turbo_speed_limit",
|
||||
Category::Core,
|
||||
Specialization::Countable | Specialization::Percentage,
|
||||
true,
|
||||
true};
|
||||
|
||||
// The currently used speed mode.
|
||||
Setting<SpeedMode> current_speed_mode{linkage, SpeedMode::Standard, "current_speed_mode", Category::Core, Specialization::Default, false, true};
|
||||
|
||||
SwitchableSetting<bool> sync_core_speed{linkage, false, "sync_core_speed", Category::Core,
|
||||
Specialization::Default};
|
||||
|
||||
|
|
@ -824,6 +849,13 @@ bool IsDockedMode();
|
|||
|
||||
float Volume();
|
||||
|
||||
// speed limit ops
|
||||
u16 SpeedLimit();
|
||||
void SetSpeedMode(const SpeedMode &mode);
|
||||
void ToggleStandardMode();
|
||||
void ToggleTurboMode();
|
||||
void ToggleSlowMode();
|
||||
|
||||
std::string GetTimeZoneString(TimeZone time_zone);
|
||||
|
||||
void LogSettings();
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ ENUM(TemperatureUnits, Celsius, Fahrenheit)
|
|||
ENUM(ExtendedDynamicState, Disabled, EDS1, EDS2, EDS3);
|
||||
ENUM(GpuLogLevel, Off, Errors, Standard, Verbose, All)
|
||||
ENUM(GameListMode, TreeView, GridView);
|
||||
ENUM(SpeedMode, Standard, Turbo, Slow);
|
||||
|
||||
template <typename Type>
|
||||
inline std::string_view CanonicalizeEnum(Type id) {
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ u64 CoreTiming::GetClockTicks() const {
|
|||
|
||||
if (Settings::values.sync_core_speed.GetValue()) {
|
||||
const auto ticks = double(fres);
|
||||
const auto speed_limit = double(Settings::values.speed_limit.GetValue())*0.01;
|
||||
const auto speed_limit = double(Settings::SpeedLimit())*0.01;
|
||||
return u64(ticks/speed_limit);
|
||||
} else {
|
||||
return fres;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
|
|
@ -95,7 +95,7 @@ s64 Conductor::GetNextTicks() const {
|
|||
if (settings.use_speed_limit.GetValue()) {
|
||||
// Scales the speed based on speed_limit setting on MC. SC is handled by
|
||||
// SpeedLimiter::DoSpeedLimiting.
|
||||
speed_scale = 100.f / settings.speed_limit.GetValue();
|
||||
speed_scale = 100.f / Settings::SpeedLimit();
|
||||
} else {
|
||||
// Run at unlocked framerate.
|
||||
speed_scale = 0.01f;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2017 Citra Emulator Project
|
||||
|
|
@ -143,7 +143,7 @@ void SpeedLimiter::DoSpeedLimiting(microseconds current_system_time_us) {
|
|||
|
||||
auto now = Clock::now();
|
||||
|
||||
const double sleep_scale = Settings::values.speed_limit.GetValue() / 100.0;
|
||||
const double sleep_scale = Settings::SpeedLimit() / 100.0;
|
||||
|
||||
// Max lag caused by slow frames. Shouldn't be more than the length of a frame at the current
|
||||
// speed percent or it will clamp too much and prevent this from properly limiting to that
|
||||
|
|
|
|||
|
|
@ -69,10 +69,10 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
|
|||
Settings,
|
||||
memory_layout_mode,
|
||||
tr("Memory Layout"),
|
||||
tr("Increases the amount of emulated RAM from 4GB of the board to the "
|
||||
"devkit 8/6GB.\nDoesn't affect performance/stability but may allow HD texture "
|
||||
tr("Increases the amount of emulated RAM.\nDoesn't affect performance/stability but may allow HD texture "
|
||||
"mods to load."));
|
||||
INSERT(Settings, use_speed_limit, QString(), QString());
|
||||
INSERT(Settings, current_speed_mode, QString(), QString());
|
||||
INSERT(Settings,
|
||||
speed_limit,
|
||||
tr("Limit Speed Percent"),
|
||||
|
|
@ -80,6 +80,14 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent)
|
|||
"faster or not.\n200% for a 30 FPS game is 60 FPS, and for a "
|
||||
"60 FPS game it will be 120 FPS.\nDisabling it means unlocking the framerate to the "
|
||||
"maximum your PC can reach."));
|
||||
|
||||
INSERT(Settings, turbo_speed_limit, tr("Turbo Speed"),
|
||||
tr("When the Turbo Speed hotkey is pressed, the speed will be limited to this "
|
||||
"percentage."));
|
||||
INSERT(Settings, slow_speed_limit, tr("Slow Speed"),
|
||||
tr("When the Slow Speed hotkey is pressed, the speed will be limited to this "
|
||||
"percentage."));
|
||||
|
||||
INSERT(Settings,
|
||||
sync_core_speed,
|
||||
tr("Synchronize Core Speed"),
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ void RestoreWindowState(std::unique_ptr<QtConfig>& qtConfig);
|
|||
// This must be in alphabetical order according to action name as it must have the same order as
|
||||
// UISetting::values.shortcuts, which is alphabetically ordered.
|
||||
// clang-format off
|
||||
const std::array<Shortcut, 30> default_hotkeys{{
|
||||
const std::array<Shortcut, 32> default_hotkeys{{
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+M"), std::string("Home+Dpad_Right"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("-"), std::string("Home+Dpad_Down"), Qt::ApplicationShortcut, true}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("="), std::string("Home+Dpad_Up"), Qt::ApplicationShortcut, true}},
|
||||
|
|
@ -265,11 +265,11 @@ const std::array<Shortcut, 30> default_hotkeys{{
|
|||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F11"), std::string("Home+B"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+O"), std::string(""), Qt::WidgetWithChildrenShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F2"), std::string("Home+A"), Qt::WidgetWithChildrenShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Browse Public Game Lobby")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+B"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Create Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+N"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Direct Connect to Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+C"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Leave Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+L"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Show Current Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+R"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Browse Public Game Lobby")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+B"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Create Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+N"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Direct Connect to Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+C"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Leave Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+L"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Show Current Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+R"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F6"), std::string("R+Plus+Minus"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F5"), std::string("L+Plus+Minus"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F7"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
|
|
@ -277,6 +277,8 @@ const std::array<Shortcut, 30> default_hotkeys{{
|
|||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Start/Stop")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F5"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F"), std::string(""), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+U"), std::string("Home+Y"), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Turbo Speed")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+Z"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Slow Speed")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+X"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F9"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Renderdoc Capture")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string(""), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+S"), std::string(""), Qt::WindowShortcut, false}},
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
// Qt on macOS doesn't define VMA shit
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include "common/settings.h"
|
||||
#include "common/settings_enums.h"
|
||||
#include "frontend_common/settings_generator.h"
|
||||
#include "qt_common/qt_string_lookup.h"
|
||||
|
|
@ -1406,12 +1407,12 @@ void MainWindow::InitializeHotkeys() {
|
|||
LinkActionShortcut(ui->action_TAS_Record, QStringLiteral("TAS Record"), true);
|
||||
LinkActionShortcut(ui->action_TAS_Reset, QStringLiteral("TAS Reset"), true);
|
||||
LinkActionShortcut(ui->action_View_Lobby,
|
||||
QStringLiteral("Multiplayer Browse Public Game Lobby"));
|
||||
LinkActionShortcut(ui->action_Start_Room, QStringLiteral("Multiplayer Create Room"));
|
||||
QStringLiteral("Browse Public Game Lobby"));
|
||||
LinkActionShortcut(ui->action_Start_Room, QStringLiteral("Create Room"));
|
||||
LinkActionShortcut(ui->action_Connect_To_Room,
|
||||
QStringLiteral("Multiplayer Direct Connect to Room"));
|
||||
LinkActionShortcut(ui->action_Show_Room, QStringLiteral("Multiplayer Show Current Room"));
|
||||
LinkActionShortcut(ui->action_Leave_Room, QStringLiteral("Multiplayer Leave Room"));
|
||||
QStringLiteral("Direct Connect to Room"));
|
||||
LinkActionShortcut(ui->action_Show_Room, QStringLiteral("Show Current Room"));
|
||||
LinkActionShortcut(ui->action_Leave_Room, QStringLiteral("Leave Room"));
|
||||
LinkActionShortcut(ui->action_Configure, QStringLiteral("Configure"));
|
||||
LinkActionShortcut(ui->action_Configure_Current_Game, QStringLiteral("Configure Current Game"));
|
||||
|
||||
|
|
@ -1440,9 +1441,25 @@ void MainWindow::InitializeHotkeys() {
|
|||
connect_shortcut(QStringLiteral("Audio Mute/Unmute"), &MainWindow::OnMute);
|
||||
connect_shortcut(QStringLiteral("Audio Volume Down"), &MainWindow::OnDecreaseVolume);
|
||||
connect_shortcut(QStringLiteral("Audio Volume Up"), &MainWindow::OnIncreaseVolume);
|
||||
connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] {
|
||||
Settings::values.use_speed_limit.SetValue(!Settings::values.use_speed_limit.GetValue());
|
||||
|
||||
connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [this] {
|
||||
Settings::ToggleStandardMode();
|
||||
const bool limited = Settings::values.use_speed_limit.GetValue();
|
||||
m_fpsSuffix = limited ? QString{} : tr("Unlocked");
|
||||
});
|
||||
|
||||
connect_shortcut(QStringLiteral("Toggle Turbo Speed"), [this] {
|
||||
Settings::ToggleTurboMode();
|
||||
const bool turbo = Settings::values.current_speed_mode.GetValue() == Settings::SpeedMode::Turbo;
|
||||
m_fpsSuffix = turbo ? tr("Turbo") : QString{};
|
||||
});
|
||||
|
||||
connect_shortcut(QStringLiteral("Toggle Slow Speed"), [this] {
|
||||
Settings::ToggleSlowMode();
|
||||
const bool slow = Settings::values.current_speed_mode.GetValue() == Settings::SpeedMode::Slow;
|
||||
m_fpsSuffix = slow ? tr("Slow") : QString{};
|
||||
});
|
||||
|
||||
connect_shortcut(QStringLiteral("Toggle Renderdoc Capture"), [] {
|
||||
if (Settings::values.enable_renderdoc_hotkey) {
|
||||
QtCommon::system->GetRenderdocAPI().ToggleCapture();
|
||||
|
|
@ -4254,14 +4271,15 @@ void MainWindow::UpdateStatusBar() {
|
|||
if (Settings::values.use_speed_limit.GetValue()) {
|
||||
emu_speed_label->setText(tr("Speed: %1% / %2%")
|
||||
.arg(results.emulation_speed * 100.0, 0, 'f', 0)
|
||||
.arg(Settings::values.speed_limit.GetValue()));
|
||||
.arg(Settings::SpeedLimit()));
|
||||
} else {
|
||||
emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0));
|
||||
}
|
||||
|
||||
game_fps_label->setText(
|
||||
tr("Game: %1 FPS").arg(std::round(results.average_game_fps), 0, 'f', 0) +
|
||||
tr(Settings::values.use_speed_limit ? "" : " (Unlocked)"));
|
||||
QString fpsText = tr("Game: %1 FPS").arg(std::round(results.average_game_fps), 0, 'f', 0);
|
||||
if (!m_fpsSuffix.isEmpty()) fpsText = fpsText % QStringLiteral(" (%1)").arg(m_fpsSuffix);
|
||||
|
||||
game_fps_label->setText(fpsText);
|
||||
|
||||
emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2));
|
||||
|
||||
|
|
|
|||
|
|
@ -518,6 +518,9 @@ private:
|
|||
QSlider* volume_slider = nullptr;
|
||||
QTimer status_bar_update_timer;
|
||||
|
||||
// Stores what suffix to add to the FPS counter, e.g. Unlocked.
|
||||
QString m_fpsSuffix{};
|
||||
|
||||
UserDataMigrator user_data_migrator;
|
||||
std::unique_ptr<QtConfig> config;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue