mirror of
https://github.com/azahar-emu/azahar.git
synced 2025-04-28 13:47:59 +03:00
Add turbo speed
hotkey (#605)
* Add the turbo slider * [WIP] Add fast forward toggle hotkey * Make Increase/Decrease speed hotkeys change turbo key instead of `frame_limit` * Allow non-runtime editable settings on `general` settings tab` * `frame_limit` is now non-runtime-editable * Disable `toggle per game speed limit` if turbo mode is set * Reset `frame_limit` back to initial value once the emulator closes * Improve `AdjustSpeedLimit` - Set frameskip value directly - Bypass if turbo mode isn't active * Some code cleanup * Move `turbo_speed_slider` from UISettings to CommonSettings Also rename to just `turbo_speed` * android: Add turbo mode hotkey * Fixed build failure + Applied clang-format * configure_general.ui Make padding on right side of sliders consistent Not sure why there's a difference here, so I just threw in a spacer * android: Corrected build failures caused by bad merge * Updated `turbo_speed_description` to be a little more descriptive * android: Corrected turbo crash caused by bad JNI function names * Updated license headers * HotkeyFunctions.kt: Fixed minor fomatting irregularities * Applied clang-format --------- Co-authored-by: kleidis <167202775+kleidis@users.noreply.github.com>
This commit is contained in:
parent
4ea8c6fda5
commit
0e0137a9ff
23 changed files with 353 additions and 55 deletions
|
@ -186,6 +186,17 @@ object NativeLibrary {
|
|||
|
||||
external fun unlinkConsole()
|
||||
|
||||
|
||||
/**
|
||||
* Turbo speed.
|
||||
*/
|
||||
external fun toggleTurboSpeed(enabled: Boolean)
|
||||
|
||||
external fun getTurboSpeedSlider(): Int
|
||||
|
||||
external fun setTurboSpeedSlider(value: Int)
|
||||
|
||||
|
||||
private var coreErrorAlertResult = false
|
||||
private val coreErrorAlertLock = Object()
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.citra.citra_emu.contracts.OpenFileResultContract
|
|||
import org.citra.citra_emu.databinding.ActivityEmulationBinding
|
||||
import org.citra.citra_emu.display.ScreenAdjustmentUtil
|
||||
import org.citra.citra_emu.features.hotkeys.HotkeyUtility
|
||||
import org.citra.citra_emu.features.hotkeys.HotkeyFunctions
|
||||
import org.citra.citra_emu.features.settings.model.BooleanSetting
|
||||
import org.citra.citra_emu.features.settings.model.IntSetting
|
||||
import org.citra.citra_emu.features.settings.model.SettingsViewModel
|
||||
|
@ -55,6 +56,7 @@ class EmulationActivity : AppCompatActivity() {
|
|||
|
||||
private lateinit var binding: ActivityEmulationBinding
|
||||
private lateinit var screenAdjustmentUtil: ScreenAdjustmentUtil
|
||||
private lateinit var hotkeyFunctions: HotkeyFunctions
|
||||
private lateinit var hotkeyUtility: HotkeyUtility
|
||||
|
||||
private val emulationFragment: EmulationFragment
|
||||
|
@ -75,7 +77,8 @@ class EmulationActivity : AppCompatActivity() {
|
|||
|
||||
binding = ActivityEmulationBinding.inflate(layoutInflater)
|
||||
screenAdjustmentUtil = ScreenAdjustmentUtil(this, windowManager, settingsViewModel.settings)
|
||||
hotkeyUtility = HotkeyUtility(screenAdjustmentUtil, this)
|
||||
hotkeyFunctions = HotkeyFunctions(settingsViewModel.settings)
|
||||
hotkeyUtility = HotkeyUtility(screenAdjustmentUtil, hotkeyFunctions, this)
|
||||
setContentView(binding.root)
|
||||
|
||||
val navHostFragment =
|
||||
|
@ -138,6 +141,7 @@ class EmulationActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
hotkeyFunctions.resetTurboSpeed()
|
||||
EmulationLifecycleUtil.clear()
|
||||
isEmulationRunning = false
|
||||
instance = null
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -10,5 +10,6 @@ enum class Hotkey(val button: Int) {
|
|||
CLOSE_GAME(10003),
|
||||
PAUSE_OR_RESUME(10004),
|
||||
QUICKSAVE(10005),
|
||||
QUICKLOAD(10006);
|
||||
QUICKLOAD(10006),
|
||||
TURBO_SPEED(10007);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.features.hotkeys
|
||||
|
||||
import android.widget.Toast
|
||||
import org.citra.citra_emu.CitraApplication
|
||||
import org.citra.citra_emu.NativeLibrary
|
||||
import org.citra.citra_emu.features.settings.model.IntSetting
|
||||
import org.citra.citra_emu.features.settings.model.Settings
|
||||
import org.citra.citra_emu.features.settings.utils.SettingsFile
|
||||
|
||||
|
||||
class HotkeyFunctions (
|
||||
private val settings: Settings
|
||||
) {
|
||||
private var normalSpeed = IntSetting.FRAME_LIMIT.int
|
||||
var isTurboSpeedEnabled = false
|
||||
|
||||
// Turbo Speed
|
||||
fun setTurboSpeed(enabled: Boolean) {
|
||||
isTurboSpeedEnabled = enabled
|
||||
toggleTurboSpeed()
|
||||
}
|
||||
|
||||
fun toggleTurboSpeed() {
|
||||
if (isTurboSpeedEnabled) {
|
||||
normalSpeed = IntSetting.FRAME_LIMIT.int
|
||||
NativeLibrary.toggleTurboSpeed(true)
|
||||
NativeLibrary.setTurboSpeedSlider(IntSetting.TURBO_SPEED.int)
|
||||
IntSetting.FRAME_LIMIT.int = IntSetting.TURBO_SPEED.int
|
||||
} else {
|
||||
NativeLibrary.toggleTurboSpeed(false)
|
||||
NativeLibrary.setTurboSpeedSlider(normalSpeed)
|
||||
IntSetting.FRAME_LIMIT.int = normalSpeed
|
||||
}
|
||||
|
||||
settings.saveSetting(IntSetting.FRAME_LIMIT, SettingsFile.FILE_NAME_CONFIG)
|
||||
NativeLibrary.reloadSettings()
|
||||
|
||||
val context = CitraApplication.appContext
|
||||
Toast.makeText(context,
|
||||
"Changed Emulation Speed to: ${IntSetting.FRAME_LIMIT.int}%", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
fun resetTurboSpeed() {
|
||||
if (isTurboSpeedEnabled) {
|
||||
isTurboSpeedEnabled = false
|
||||
NativeLibrary.toggleTurboSpeed(false)
|
||||
IntSetting.FRAME_LIMIT.int = normalSpeed
|
||||
|
||||
settings.saveSetting(IntSetting.FRAME_LIMIT, SettingsFile.FILE_NAME_CONFIG)
|
||||
NativeLibrary.reloadSettings()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -11,9 +11,12 @@ import org.citra.citra_emu.R
|
|||
import org.citra.citra_emu.utils.EmulationLifecycleUtil
|
||||
import org.citra.citra_emu.display.ScreenAdjustmentUtil
|
||||
|
||||
class HotkeyUtility(private val screenAdjustmentUtil: ScreenAdjustmentUtil, private val context: Context) {
|
||||
class HotkeyUtility(
|
||||
private val screenAdjustmentUtil: ScreenAdjustmentUtil,
|
||||
private val hotkeyFunctions: HotkeyFunctions,
|
||||
private val context: Context) {
|
||||
|
||||
val hotkeyButtons = Hotkey.entries.map { it.button }
|
||||
private val hotkeyButtons = Hotkey.entries.map { it.button }
|
||||
|
||||
fun handleHotkey(bindedButton: Int): Boolean {
|
||||
if(hotkeyButtons.contains(bindedButton)) {
|
||||
|
@ -22,6 +25,7 @@ class HotkeyUtility(private val screenAdjustmentUtil: ScreenAdjustmentUtil, priv
|
|||
Hotkey.CYCLE_LAYOUT.button -> screenAdjustmentUtil.cycleLayouts()
|
||||
Hotkey.CLOSE_GAME.button -> EmulationLifecycleUtil.closeGame()
|
||||
Hotkey.PAUSE_OR_RESUME.button -> EmulationLifecycleUtil.pauseOrResume()
|
||||
Hotkey.TURBO_SPEED.button -> hotkeyFunctions.setTurboSpeed(!hotkeyFunctions.isTurboSpeedEnabled)
|
||||
Hotkey.QUICKSAVE.button -> {
|
||||
NativeLibrary.saveState(NativeLibrary.QUICKSAVE_SLOT)
|
||||
Toast.makeText(context,
|
||||
|
|
|
@ -65,7 +65,9 @@ enum class IntSetting(
|
|||
DELAY_RENDER_THREAD_US("delay_game_render_thread_us", Settings.SECTION_RENDERER, 0),
|
||||
USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, 0),
|
||||
ORIENTATION_OPTION("screen_orientation", Settings.SECTION_LAYOUT, 2),
|
||||
DISABLE_RIGHT_EYE_RENDER("disable_right_eye_render", Settings.SECTION_RENDERER, 0);
|
||||
DISABLE_RIGHT_EYE_RENDER("disable_right_eye_render", Settings.SECTION_RENDERER, 0),
|
||||
TURBO_SPEED("turbo_speed", Settings.SECTION_CORE, 200);
|
||||
|
||||
override var int: Int = defaultValue
|
||||
|
||||
override val valueAsString: String
|
||||
|
@ -95,6 +97,7 @@ enum class IntSetting(
|
|||
AUDIO_INPUT_TYPE,
|
||||
USE_ARTIC_BASE_CONTROLLER,
|
||||
SHADERS_ACCURATE_MUL,
|
||||
FRAME_LIMIT
|
||||
)
|
||||
|
||||
fun from(key: String): IntSetting? = IntSetting.values().firstOrNull { it.key == key }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -139,6 +139,7 @@ class Settings {
|
|||
const val HOTKEY_PAUSE_OR_RESUME = "hotkey_pause_or_resume_game"
|
||||
const val HOTKEY_QUICKSAVE = "hotkey_quickload"
|
||||
const val HOTKEY_QUICKlOAD = "hotkey_quickpause"
|
||||
const val HOTKEY_TURBO_SPEED = "hotkey_turbo_speed"
|
||||
|
||||
val buttonKeys = listOf(
|
||||
KEY_BUTTON_A,
|
||||
|
@ -204,7 +205,8 @@ class Settings {
|
|||
HOTKEY_CLOSE_GAME,
|
||||
HOTKEY_PAUSE_OR_RESUME,
|
||||
HOTKEY_QUICKSAVE,
|
||||
HOTKEY_QUICKlOAD
|
||||
HOTKEY_QUICKlOAD,
|
||||
HOTKEY_TURBO_SPEED
|
||||
)
|
||||
val hotkeyTitles = listOf(
|
||||
R.string.emulation_swap_screens,
|
||||
|
@ -213,6 +215,7 @@ class Settings {
|
|||
R.string.emulation_toggle_pause,
|
||||
R.string.emulation_quicksave,
|
||||
R.string.emulation_quickload,
|
||||
R.string.emulation_toggle_turbo_speed
|
||||
)
|
||||
|
||||
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -133,6 +133,7 @@ class InputBindingSetting(
|
|||
Settings.HOTKEY_PAUSE_OR_RESUME -> Hotkey.PAUSE_OR_RESUME.button
|
||||
Settings.HOTKEY_QUICKSAVE -> Hotkey.QUICKSAVE.button
|
||||
Settings.HOTKEY_QUICKlOAD -> Hotkey.QUICKLOAD.button
|
||||
Settings.HOTKEY_TURBO_SPEED -> Hotkey.TURBO_SPEED.button
|
||||
else -> -1
|
||||
}
|
||||
|
||||
|
|
|
@ -237,6 +237,18 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
|||
IntSetting.FRAME_LIMIT.defaultValue.toFloat()
|
||||
)
|
||||
)
|
||||
add(
|
||||
SliderSetting(
|
||||
IntSetting.TURBO_SPEED,
|
||||
R.string.turbo_speed,
|
||||
R.string.turbo_speed_description,
|
||||
100,
|
||||
400,
|
||||
"%",
|
||||
IntSetting.TURBO_SPEED.key,
|
||||
IntSetting.TURBO_SPEED.defaultValue.toFloat()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -149,7 +149,7 @@ void Config::ReadValues() {
|
|||
ReadSetting("Renderer", Settings::values.use_vsync_new);
|
||||
ReadSetting("Renderer", Settings::values.texture_filter);
|
||||
ReadSetting("Renderer", Settings::values.texture_sampling);
|
||||
|
||||
ReadSetting("Renderer", Settings::values.turbo_speed);
|
||||
// Workaround to map Android setting for enabling the frame limiter to the format Citra expects
|
||||
if (sdl2_config->GetBoolean("Renderer", "use_frame_limit", true)) {
|
||||
ReadSetting("Renderer", Settings::values.frame_limit);
|
||||
|
|
|
@ -773,6 +773,22 @@ void Java_org_citra_citra_1emu_NativeLibrary_logDeviceInfo([[maybe_unused]] JNIE
|
|||
LOG_INFO(Frontend, "Host OS: Android API level {}", android_get_device_api_level());
|
||||
}
|
||||
|
||||
void JNICALL Java_org_citra_citra_1emu_NativeLibrary_toggleTurboSpeed([[maybe_unused]] JNIEnv* env,
|
||||
[[maybe_unused]] jobject obj,
|
||||
jboolean enabled) {
|
||||
Settings::values.turbo_speed = enabled ? true : false;
|
||||
}
|
||||
|
||||
jint JNICALL Java_org_citra_citra_1emu_NativeLibrary_getTurboSpeedSlider(
|
||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) {
|
||||
return static_cast<jint>(Settings::values.turbo_speed);
|
||||
}
|
||||
|
||||
void JNICALL Java_org_citra_citra_1emu_NativeLibrary_setTurboSpeedSlider(
|
||||
[[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj, jint value) {
|
||||
Settings::values.turbo_speed = value;
|
||||
}
|
||||
|
||||
jboolean Java_org_citra_citra_1emu_NativeLibrary_isFullConsoleLinked(JNIEnv* env, jobject obj) {
|
||||
return HW::UniqueData::IsFullConsoleLinked();
|
||||
}
|
||||
|
|
|
@ -242,11 +242,14 @@
|
|||
<string name="asynchronous_gpu">Enable asynchronous GPU emulation</string>
|
||||
<string name="asynchronous_gpu_description">Uses a separate thread to emulate the GPU asynchronously. When enabled, performance will be improved.</string>
|
||||
<string name="frame_limit_enable">Limit Speed</string>
|
||||
<string name="expand_to_cutout_area">Expand to Cutout Area</string>
|
||||
<string name="expand_to_cutout_area_description">Expands the display area to include the cutout (or notch) area.</string>
|
||||
<string name="frame_limit_enable_description">When enabled, emulation speed will be limited to a specified percentage of normal speed.</string>
|
||||
<string name="frame_limit_enable_description">When enabled, emulation speed will be limited to a specified percentage of normal speed. If disabled, emulation speed will be uncapped and the turbo speed hotkey will not work.</string>
|
||||
<string name="frame_limit_slider">Limit Speed Percent</string>
|
||||
<string name="frame_limit_slider_description">Specifies the percentage to limit emulation speed. With the default of 100% emulation will be limited to normal speed. Values higher or lower will increase or decrease the speed limit.</string>
|
||||
<string name="expand_to_cutout_area">Expand to Cutout Area</string>
|
||||
<string name="expand_to_cutout_area_description">Expands the display area to include the cutout (or notch) area.</string>
|
||||
<string name="emulation_toggle_turbo_speed">Turbo Speed</string>
|
||||
<string name="turbo_speed">Turbo Speed</string>
|
||||
<string name="turbo_speed_description">Emulation speed limit used while the turbo hotkey is active.</string>
|
||||
<string name="internal_resolution">Internal Resolution</string>
|
||||
<string name="internal_resolution_description">Specifies the resolution used to render at. A high resolution will improve visual quality a lot but is also quite heavy on performance and might cause glitches in certain applications.</string>
|
||||
<string name="internal_resolution_setting_auto">Auto (Screen Size)</string>
|
||||
|
|
|
@ -785,6 +785,11 @@ void GMainWindow::InitializeHotkeys() {
|
|||
}
|
||||
});
|
||||
connect_shortcut(QStringLiteral("Toggle Per-Application Speed"), [&] {
|
||||
if (!hotkey_registry
|
||||
.GetKeySequence(QStringLiteral("Main Window"), QStringLiteral("Toggle Turbo Mode"))
|
||||
.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Settings::values.frame_limit.SetGlobal(!Settings::values.frame_limit.UsingGlobal());
|
||||
UpdateStatusBar();
|
||||
});
|
||||
|
@ -792,31 +797,12 @@ void GMainWindow::InitializeHotkeys() {
|
|||
[&] { Settings::values.dump_textures = !Settings::values.dump_textures; });
|
||||
connect_shortcut(QStringLiteral("Toggle Custom Textures"),
|
||||
[&] { Settings::values.custom_textures = !Settings::values.custom_textures; });
|
||||
// We use "static" here in order to avoid capturing by lambda due to a MSVC bug, which makes
|
||||
// the variable hold a garbage value after this function exits
|
||||
static constexpr u16 SPEED_LIMIT_STEP = 5;
|
||||
connect_shortcut(QStringLiteral("Increase Speed Limit"), [&] {
|
||||
if (Settings::values.frame_limit.GetValue() == 0) {
|
||||
return;
|
||||
}
|
||||
if (Settings::values.frame_limit.GetValue() < 995 - SPEED_LIMIT_STEP) {
|
||||
Settings::values.frame_limit.SetValue(Settings::values.frame_limit.GetValue() +
|
||||
SPEED_LIMIT_STEP);
|
||||
} else {
|
||||
Settings::values.frame_limit = 0;
|
||||
}
|
||||
UpdateStatusBar();
|
||||
});
|
||||
connect_shortcut(QStringLiteral("Decrease Speed Limit"), [&] {
|
||||
if (Settings::values.frame_limit.GetValue() == 0) {
|
||||
Settings::values.frame_limit = 995;
|
||||
} else if (Settings::values.frame_limit.GetValue() > SPEED_LIMIT_STEP) {
|
||||
Settings::values.frame_limit.SetValue(Settings::values.frame_limit.GetValue() -
|
||||
SPEED_LIMIT_STEP);
|
||||
UpdateStatusBar();
|
||||
}
|
||||
UpdateStatusBar();
|
||||
});
|
||||
|
||||
connect_shortcut(QStringLiteral("Toggle Turbo Mode"), &GMainWindow::ToggleEmulationSpeed);
|
||||
|
||||
connect_shortcut(QStringLiteral("Increase Speed Limit"), [&] { AdjustSpeedLimit(true); });
|
||||
|
||||
connect_shortcut(QStringLiteral("Decrease Speed Limit"), [&] { AdjustSpeedLimit(false); });
|
||||
|
||||
connect_shortcut(QStringLiteral("Audio Mute/Unmute"), &GMainWindow::OnMute);
|
||||
connect_shortcut(QStringLiteral("Audio Volume Down"), &GMainWindow::OnDecreaseVolume);
|
||||
|
@ -2363,6 +2349,7 @@ void GMainWindow::OnMenuRecentFile() {
|
|||
}
|
||||
|
||||
void GMainWindow::OnStartGame() {
|
||||
GetInitialFrameLimit();
|
||||
qt_cameras->ResumeCameras();
|
||||
|
||||
PreventOSSleep();
|
||||
|
@ -2422,6 +2409,12 @@ void GMainWindow::OnPauseContinueGame() {
|
|||
}
|
||||
|
||||
void GMainWindow::OnStopGame() {
|
||||
if (turbo_mode_active) {
|
||||
turbo_mode_active = false;
|
||||
Settings::values.frame_limit.SetValue(initial_frame_limit);
|
||||
UpdateStatusBar();
|
||||
}
|
||||
|
||||
play_time_manager->Stop();
|
||||
// Update game list to show new play time
|
||||
game_list->PopulateAsync(UISettings::values.game_dirs);
|
||||
|
@ -2573,6 +2566,54 @@ void GMainWindow::ChangeSmallScreenPosition() {
|
|||
UpdateSecondaryWindowVisibility();
|
||||
}
|
||||
|
||||
void GMainWindow::GetInitialFrameLimit() {
|
||||
initial_frame_limit = Settings::values.frame_limit.GetValue();
|
||||
turbo_mode_active = false;
|
||||
}
|
||||
|
||||
void GMainWindow::ToggleEmulationSpeed() {
|
||||
static bool key_pressed = false; // Prevent spam on hold
|
||||
|
||||
if (!key_pressed) {
|
||||
key_pressed = true;
|
||||
turbo_mode_active = !turbo_mode_active;
|
||||
|
||||
if (turbo_mode_active) {
|
||||
Settings::values.frame_limit.SetValue(Settings::values.turbo_speed.GetValue());
|
||||
} else {
|
||||
Settings::values.frame_limit.SetValue(initial_frame_limit);
|
||||
}
|
||||
|
||||
UpdateStatusBar();
|
||||
QTimer::singleShot(200, [] { key_pressed = false; });
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::AdjustSpeedLimit(bool increase) {
|
||||
if (!turbo_mode_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int SPEED_LIMIT_STEP = 5;
|
||||
int turbo_speed = Settings::values.turbo_speed.GetValue();
|
||||
|
||||
if (increase) {
|
||||
if (turbo_speed < 995) {
|
||||
Settings::values.turbo_speed.SetValue(turbo_speed + SPEED_LIMIT_STEP);
|
||||
Settings::values.frame_limit.SetValue(turbo_speed + SPEED_LIMIT_STEP);
|
||||
}
|
||||
} else {
|
||||
if (turbo_speed > SPEED_LIMIT_STEP) {
|
||||
Settings::values.turbo_speed.SetValue(turbo_speed - SPEED_LIMIT_STEP);
|
||||
Settings::values.frame_limit.SetValue(turbo_speed - SPEED_LIMIT_STEP);
|
||||
}
|
||||
}
|
||||
|
||||
if (turbo_mode_active) {
|
||||
UpdateStatusBar();
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::ToggleScreenLayout() {
|
||||
const Settings::LayoutOption new_layout = []() {
|
||||
switch (Settings::values.layout_option.GetValue()) {
|
||||
|
|
|
@ -222,6 +222,7 @@ private:
|
|||
|
||||
private slots:
|
||||
void OnStartGame();
|
||||
void GetInitialFrameLimit();
|
||||
void OnRestartGame();
|
||||
void OnPauseGame();
|
||||
void OnPauseContinueGame();
|
||||
|
@ -260,6 +261,8 @@ private slots:
|
|||
void ToggleSecondaryFullscreen();
|
||||
void ChangeScreenLayout();
|
||||
void ChangeSmallScreenPosition();
|
||||
void ToggleEmulationSpeed();
|
||||
void AdjustSpeedLimit(bool increase);
|
||||
void UpdateSecondaryWindowVisibility();
|
||||
void ToggleScreenLayout();
|
||||
void OnSwapScreens();
|
||||
|
@ -348,6 +351,9 @@ private:
|
|||
UserDataMigrator user_data_migrator;
|
||||
std::unique_ptr<QtConfig> config;
|
||||
|
||||
// Hotkeys
|
||||
bool turbo_mode_active = false;
|
||||
|
||||
// Whether emulation is currently running in Citra.
|
||||
bool emulation_running = false;
|
||||
std::unique_ptr<EmuThread> emu_thread;
|
||||
|
@ -405,6 +411,8 @@ private:
|
|||
u32 newest_slot;
|
||||
u64 newest_slot_time;
|
||||
|
||||
int initial_frame_limit;
|
||||
|
||||
// Secondary window actions
|
||||
QAction* action_secondary_fullscreen;
|
||||
QAction* action_secondary_toggle_screen;
|
||||
|
|
|
@ -54,7 +54,7 @@ const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> QtConfi
|
|||
// 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<UISettings::Shortcut, 35> QtConfig::default_hotkeys {{
|
||||
const std::array<UISettings::Shortcut, 36> QtConfig::default_hotkeys {{
|
||||
{QStringLiteral("Advance Frame"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
|
||||
{QStringLiteral("Audio Mute/Unmute"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+M"), Qt::WindowShortcut}},
|
||||
{QStringLiteral("Audio Volume Down"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::WindowShortcut}},
|
||||
|
@ -83,6 +83,7 @@ const std::array<UISettings::Shortcut, 35> QtConfig::default_hotkeys {{
|
|||
{QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}},
|
||||
{QStringLiteral("Swap Screens"), QStringLiteral("Main Window"), {QStringLiteral("F9"), Qt::WindowShortcut}},
|
||||
{QStringLiteral("Toggle 3D"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+3"), Qt::ApplicationShortcut}},
|
||||
{QStringLiteral("Toggle Turbo Mode"), QStringLiteral("Main Window"), {QStringLiteral(""), Qt::ApplicationShortcut}},
|
||||
{QStringLiteral("Toggle Custom Textures"), QStringLiteral("Main Window"), {QStringLiteral("F7"), Qt::ApplicationShortcut}},
|
||||
{QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}},
|
||||
{QStringLiteral("Toggle Frame Advancing"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+A"), Qt::ApplicationShortcut}},
|
||||
|
@ -807,6 +808,7 @@ void QtConfig::ReadUIValues() {
|
|||
ReadBasicSetting(UISettings::values.display_titlebar);
|
||||
ReadBasicSetting(UISettings::values.show_filter_bar);
|
||||
ReadBasicSetting(UISettings::values.show_status_bar);
|
||||
ReadBasicSetting(Settings::values.turbo_speed);
|
||||
ReadBasicSetting(UISettings::values.confirm_before_closing);
|
||||
ReadBasicSetting(UISettings::values.save_state_warning);
|
||||
ReadBasicSetting(UISettings::values.first_start);
|
||||
|
@ -1316,6 +1318,7 @@ void QtConfig::SaveUIValues() {
|
|||
WriteBasicSetting(UISettings::values.show_filter_bar);
|
||||
WriteBasicSetting(UISettings::values.show_status_bar);
|
||||
WriteBasicSetting(UISettings::values.confirm_before_closing);
|
||||
WriteBasicSetting(Settings::values.turbo_speed);
|
||||
WriteBasicSetting(UISettings::values.save_state_warning);
|
||||
WriteBasicSetting(UISettings::values.first_start);
|
||||
WriteBasicSetting(UISettings::values.callout_flags);
|
||||
|
|
|
@ -26,7 +26,7 @@ public:
|
|||
|
||||
static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
|
||||
static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> default_analogs;
|
||||
static const std::array<UISettings::Shortcut, 35> default_hotkeys;
|
||||
static const std::array<UISettings::Shortcut, 36> default_hotkeys;
|
||||
|
||||
private:
|
||||
void Initialize(const std::string& config_name);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2016 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -28,7 +28,7 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Cor
|
|||
bool enable_web_config)
|
||||
: QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, registry{registry_},
|
||||
system{system_}, is_powered_on{system.IsPoweredOn()},
|
||||
general_tab{std::make_unique<ConfigureGeneral>(this)},
|
||||
general_tab{std::make_unique<ConfigureGeneral>(is_powered_on, this)},
|
||||
system_tab{std::make_unique<ConfigureSystem>(system, this)},
|
||||
input_tab{std::make_unique<ConfigureInput>(system, this)},
|
||||
hotkeys_tab{std::make_unique<ConfigureHotkeys>(this)},
|
||||
|
|
|
@ -24,11 +24,16 @@ static constexpr int SettingsToSlider(int value) {
|
|||
return (value - 5) / 5;
|
||||
}
|
||||
|
||||
ConfigureGeneral::ConfigureGeneral(QWidget* parent)
|
||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureGeneral>()) {
|
||||
|
||||
ConfigureGeneral::ConfigureGeneral(bool is_powered_on, QWidget* parent)
|
||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureGeneral>()), is_powered_on{is_powered_on} {
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->turbo_speed, &QSlider::valueChanged, this, [&](int value) {
|
||||
Settings::values.turbo_speed.SetValue(SliderToSettings(value));
|
||||
ui->turbo_speed_display_label->setText(
|
||||
QStringLiteral("%1%").arg(Settings::values.turbo_speed.GetValue()));
|
||||
});
|
||||
|
||||
// Set a minimum width for the label to prevent the slider from changing size.
|
||||
// This scales across DPIs, and is acceptable for uncapitalized strings.
|
||||
const auto width = static_cast<int>(tr("unthrottled").size() * 6);
|
||||
|
@ -75,6 +80,10 @@ ConfigureGeneral::~ConfigureGeneral() = default;
|
|||
|
||||
void ConfigureGeneral::SetConfiguration() {
|
||||
if (Settings::IsConfiguringGlobal()) {
|
||||
ui->turbo_speed->setValue(SettingsToSlider(Settings::values.turbo_speed.GetValue()));
|
||||
ui->turbo_speed_display_label->setText(
|
||||
QStringLiteral("%1%").arg(Settings::values.turbo_speed.GetValue()));
|
||||
|
||||
ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue());
|
||||
ui->toggle_background_pause->setChecked(
|
||||
UISettings::values.pause_when_in_background.GetValue());
|
||||
|
@ -103,7 +112,10 @@ void ConfigureGeneral::SetConfiguration() {
|
|||
}
|
||||
|
||||
if (!Settings::IsConfiguringGlobal()) {
|
||||
if (Settings::values.frame_limit.UsingGlobal()) {
|
||||
if (is_powered_on) {
|
||||
ui->emulation_speed_combo->setEnabled(false);
|
||||
ui->frame_limit->setEnabled(false);
|
||||
} else if (Settings::values.frame_limit.UsingGlobal()) {
|
||||
ui->emulation_speed_combo->setCurrentIndex(0);
|
||||
ui->frame_limit->setEnabled(false);
|
||||
} else {
|
||||
|
@ -182,7 +194,11 @@ void ConfigureGeneral::RetranslateUI() {
|
|||
|
||||
void ConfigureGeneral::SetupPerGameUI() {
|
||||
if (Settings::IsConfiguringGlobal()) {
|
||||
if (is_powered_on) {
|
||||
ui->frame_limit->setEnabled(false);
|
||||
} else {
|
||||
ui->frame_limit->setEnabled(Settings::values.frame_limit.UsingGlobal());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -198,6 +214,7 @@ void ConfigureGeneral::SetupPerGameUI() {
|
|||
ConfigurationShared::SetHighlight(ui->widget_screenshot, index == 1);
|
||||
});
|
||||
|
||||
ui->turbo_speed->setVisible(false);
|
||||
ui->general_group->setVisible(false);
|
||||
ui->button_reset_defaults->setVisible(false);
|
||||
ui->toggle_gamemode->setVisible(false);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2016 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -17,7 +17,7 @@ class ConfigureGeneral : public QWidget {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConfigureGeneral(QWidget* parent = nullptr);
|
||||
explicit ConfigureGeneral(bool is_powered_on, QWidget* parent = nullptr);
|
||||
~ConfigureGeneral() override;
|
||||
|
||||
void ResetDefaults();
|
||||
|
@ -29,4 +29,5 @@ public:
|
|||
|
||||
private:
|
||||
std::unique_ptr<Ui::ConfigureGeneral> ui;
|
||||
bool is_powered_on;
|
||||
};
|
||||
|
|
|
@ -147,6 +147,82 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="turbo_speed_layout" native="true">
|
||||
<layout class="QHBoxLayout" name="turbo_speed_layout_inner">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="turbo_speed_label">
|
||||
<property name="text">
|
||||
<string>Turbo Speed:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="turbo_speed">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>198</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>19</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="turbo_speed_display_label">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2017 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
|
@ -98,6 +98,37 @@ void ConfigureHotkeys::Configure(QModelIndex index) {
|
|||
}
|
||||
const auto [key_sequence_used, used_action] = IsUsedKey(key_sequence);
|
||||
|
||||
// Check for turbo/per-game speed conflict. Needed to prevent the user from binding both hotkeys
|
||||
// to the same action. Which cuases problems resetting the frame limit.to the inititla value.
|
||||
const QString current_action =
|
||||
model->data(model->index(index.row(), 0, index.parent())).toString();
|
||||
const bool is_turbo = current_action == tr("Toggle Turbo Mode");
|
||||
const bool is_per_game = current_action == tr("Toggle Per-Game Speed");
|
||||
|
||||
if (is_turbo || is_per_game) {
|
||||
QString other_action = is_turbo ? tr("Toggle Per-Game Speed") : tr("Toggle Turbo Mode");
|
||||
QKeySequence other_sequence;
|
||||
|
||||
for (int r = 0; r < model->rowCount(); ++r) {
|
||||
const QStandardItem* const parent = model->item(r, 0);
|
||||
for (int r2 = 0; r2 < parent->rowCount(); ++r2) {
|
||||
if (parent->child(r2, 0)->text() == other_action) {
|
||||
other_sequence = QKeySequence::fromString(
|
||||
parent->child(r2, hotkey_column)->text(), QKeySequence::NativeText);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show warning if either hotkey is already set
|
||||
if (!key_sequence.isEmpty() && !other_sequence.isEmpty()) {
|
||||
QMessageBox::warning(
|
||||
this, tr("Conflicting Key Sequence"),
|
||||
tr("The per-game speed and turbo speed hotkeys cannot be bound at the same time."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (key_sequence_used && key_sequence != QKeySequence(previous_key.toString())) {
|
||||
QMessageBox::warning(
|
||||
this, tr("Conflicting Key Sequence"),
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
@ -35,7 +40,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString
|
|||
|
||||
const bool is_powered_on = system.IsPoweredOn();
|
||||
audio_tab = std::make_unique<ConfigureAudio>(is_powered_on, this);
|
||||
general_tab = std::make_unique<ConfigureGeneral>(this);
|
||||
general_tab = std::make_unique<ConfigureGeneral>(is_powered_on, this);
|
||||
enhancements_tab = std::make_unique<ConfigureEnhancements>(this);
|
||||
layout_tab = std::make_unique<ConfigureLayout>(this);
|
||||
graphics_tab =
|
||||
|
|
|
@ -497,6 +497,7 @@ struct Values {
|
|||
Setting<bool> use_shader_jit{true, "use_shader_jit"};
|
||||
SwitchableSetting<u32, true> resolution_factor{1, 0, 10, "resolution_factor"};
|
||||
SwitchableSetting<double, true> frame_limit{100, 0, 1000, "frame_limit"};
|
||||
SwitchableSetting<int, true> turbo_speed{200, 0, 1000, "turbo_speed"};
|
||||
SwitchableSetting<TextureFilter> texture_filter{TextureFilter::NoFilter, "texture_filter"};
|
||||
SwitchableSetting<TextureSampling> texture_sampling{TextureSampling::GameControlled,
|
||||
"texture_sampling"};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue