mirror of
https://github.com/stenzek/duckstation.git
synced 2025-06-07 12:05:52 +00:00
CDROM: Add 'maximum' read speedup option
"Instant" seek is now renamed to Maximum as well, for consistency.
This commit is contained in:
parent
0ad0859e9d
commit
561397a53c
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#include "cdrom.h"
|
||||
@ -75,7 +75,7 @@ enum : u32
|
||||
|
||||
static constexpr u8 INTERRUPT_REGISTER_MASK = 0x1F;
|
||||
|
||||
static constexpr TickCount MIN_SEEK_TICKS = 30000;
|
||||
static constexpr TickCount INSTANT_SEEK_OR_READ_TICKS = 30000;
|
||||
|
||||
enum class Interrupt : u8
|
||||
{
|
||||
@ -311,6 +311,7 @@ static void SendAsyncErrorResponse(u8 stat_bits = STAT_ERROR, u8 reason = 0x80);
|
||||
static void UpdateStatusRegister();
|
||||
static void UpdateInterruptRequest();
|
||||
static bool HasPendingDiscEvent();
|
||||
static bool CanUseReadSpeedup();
|
||||
|
||||
static TickCount GetAckDelayForCommand(Command command);
|
||||
static TickCount GetTicksForSpinUp();
|
||||
@ -1469,6 +1470,12 @@ bool CDROM::HasPendingDiscEvent()
|
||||
return (s_state.drive_event.IsActive() && s_state.drive_event.GetTicksUntilNextExecution() <= 0);
|
||||
}
|
||||
|
||||
bool CDROM::CanUseReadSpeedup()
|
||||
{
|
||||
// Only use read speedup in 2X mode and when we're not playing/filtering XA.
|
||||
return (!s_state.mode.cdda && !s_state.mode.xa_enable && s_state.mode.double_speed);
|
||||
}
|
||||
|
||||
TickCount CDROM::GetAckDelayForCommand(Command command)
|
||||
{
|
||||
if (command == Command::Init)
|
||||
@ -1503,7 +1510,7 @@ TickCount CDROM::GetTicksForRead()
|
||||
{
|
||||
const TickCount tps = System::GetTicksPerSecond();
|
||||
|
||||
if (g_settings.cdrom_read_speedup > 1 && !s_state.mode.cdda && !s_state.mode.xa_enable && s_state.mode.double_speed)
|
||||
if (g_settings.cdrom_read_speedup > 1 && CanUseReadSpeedup())
|
||||
return tps / (150 * g_settings.cdrom_read_speedup);
|
||||
|
||||
return s_state.mode.double_speed ? (tps / 150) : (tps / 75);
|
||||
@ -1561,7 +1568,7 @@ u32 CDROM::GetSectorsPerTrack(CDImage::LBA lba)
|
||||
TickCount CDROM::GetTicksForSeek(CDImage::LBA new_lba, bool ignore_speed_change)
|
||||
{
|
||||
if (g_settings.cdrom_seek_speedup == 0)
|
||||
return System::ScaleTicksToOverclock(MIN_SEEK_TICKS);
|
||||
return System::ScaleTicksToOverclock(INSTANT_SEEK_OR_READ_TICKS);
|
||||
|
||||
u32 ticks = 0;
|
||||
|
||||
@ -1631,7 +1638,7 @@ TickCount CDROM::GetTicksForSeek(CDImage::LBA new_lba, bool ignore_speed_change)
|
||||
}
|
||||
|
||||
if (g_settings.cdrom_seek_speedup > 1)
|
||||
ticks = std::max<u32>(ticks / g_settings.cdrom_seek_speedup, MIN_SEEK_TICKS);
|
||||
ticks = std::max<u32>(ticks / g_settings.cdrom_seek_speedup, INSTANT_SEEK_OR_READ_TICKS);
|
||||
|
||||
if (s_state.drive_state == DriveState::ChangingSpeedOrTOCRead && !ignore_speed_change)
|
||||
{
|
||||
@ -1659,6 +1666,9 @@ TickCount CDROM::GetTicksForPause()
|
||||
if (!IsReadingOrPlaying())
|
||||
return 7000;
|
||||
|
||||
if (g_settings.cdrom_read_speedup == 0 && CanUseReadSpeedup())
|
||||
return System::ScaleTicksToOverclock(INSTANT_SEEK_OR_READ_TICKS);
|
||||
|
||||
const u32 sectors_per_track = GetSectorsPerTrack(s_state.current_lba);
|
||||
const TickCount ticks_per_read = GetTicksForRead();
|
||||
|
||||
@ -2803,7 +2813,7 @@ void CDROM::BeginSeeking(bool logical, bool read_after_seek, bool play_after_see
|
||||
{
|
||||
DEV_COLOR_LOG(StrongCyan, "Completing seek instantly due to not passing target {}.",
|
||||
LBAToMSFString(seek_lba - SUBQ_SECTOR_SKEW));
|
||||
seek_time = MIN_SEEK_TICKS;
|
||||
seek_time = INSTANT_SEEK_OR_READ_TICKS;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3884,6 +3894,18 @@ void CDROM::CheckForSectorBufferReadComplete()
|
||||
s_state.request_register.BFRD = (s_state.request_register.BFRD && sb.position < sb.size);
|
||||
s_state.status.DRQSTS = s_state.request_register.BFRD;
|
||||
|
||||
// Maximum/immediate read speedup. Wait for the data portion of the sector to be read.
|
||||
if (s_state.drive_state == DriveState::Reading &&
|
||||
sb.position >=
|
||||
(s_state.mode.read_raw_sector ? (MODE2_HEADER_SIZE + DATA_SECTOR_OUTPUT_SIZE) : DATA_SECTOR_OUTPUT_SIZE) &&
|
||||
CanUseReadSpeedup() && g_settings.cdrom_read_speedup == 0)
|
||||
{
|
||||
const TickCount remaining_time = s_state.drive_event.GetTicksUntilNextExecution();
|
||||
const TickCount instant_ticks = System::ScaleTicksToOverclock(INSTANT_SEEK_OR_READ_TICKS);
|
||||
if (remaining_time > instant_ticks)
|
||||
s_state.drive_event.Schedule(instant_ticks);
|
||||
}
|
||||
|
||||
// Buffer complete?
|
||||
if (sb.position >= sb.size)
|
||||
{
|
||||
|
@ -311,6 +311,12 @@ static void DrawIntListSetting(SettingsInterface* bsi, const char* title, const
|
||||
float height = ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT,
|
||||
ImFont* font = UIStyle.LargeFont, ImFont* summary_font = UIStyle.MediumFont,
|
||||
const char* tr_context = TR_CONTEXT);
|
||||
static void DrawIntListSetting(SettingsInterface* bsi, const char* title, const char* summary, const char* section,
|
||||
const char* key, int default_value, std::span<const char* const> options,
|
||||
bool translate_options, std::span<const int> values, bool enabled = true,
|
||||
float height = ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT,
|
||||
ImFont* font = UIStyle.LargeFont, ImFont* summary_font = UIStyle.MediumFont,
|
||||
const char* tr_context = TR_CONTEXT);
|
||||
static void DrawIntRangeSetting(SettingsInterface* bsi, const char* title, const char* summary, const char* section,
|
||||
const char* key, int default_value, int min_value, int max_value,
|
||||
const char* format = "%d", bool enabled = true,
|
||||
@ -2064,6 +2070,75 @@ void FullscreenUI::DrawIntListSetting(SettingsInterface* bsi, const char* title,
|
||||
}
|
||||
}
|
||||
|
||||
void FullscreenUI::DrawIntListSetting(SettingsInterface* bsi, const char* title, const char* summary,
|
||||
const char* section, const char* key, int default_value,
|
||||
std::span<const char* const> options, bool translate_options,
|
||||
std::span<const int> values, bool enabled, float height, ImFont* font,
|
||||
ImFont* summary_font, const char* tr_context)
|
||||
{
|
||||
static constexpr auto value_to_index = [](s32 value, const std::span<const int> values) {
|
||||
for (size_t i = 0; i < values.size(); i++)
|
||||
{
|
||||
if (values[i] == value)
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
DebugAssert(options.size() == values.size());
|
||||
|
||||
const bool game_settings = IsEditingGameSettings(bsi);
|
||||
|
||||
const std::optional<int> value =
|
||||
bsi->GetOptionalIntValue(section, key, game_settings ? std::nullopt : std::optional<int>(default_value));
|
||||
const int index = value.has_value() ? value_to_index(value.value(), values) : -1;
|
||||
const char* value_text =
|
||||
(value.has_value()) ?
|
||||
((index < 0 || static_cast<size_t>(index) >= options.size()) ?
|
||||
FSUI_CSTR("Unknown") :
|
||||
(translate_options ? Host::TranslateToCString(tr_context, options[index]) : options[index])) :
|
||||
FSUI_CSTR("Use Global Setting");
|
||||
|
||||
if (MenuButtonWithValue(title, summary, value_text, enabled, height, font, summary_font))
|
||||
{
|
||||
ImGuiFullscreen::ChoiceDialogOptions cd_options;
|
||||
cd_options.reserve(options.size() + 1);
|
||||
if (game_settings)
|
||||
cd_options.emplace_back(FSUI_STR("Use Global Setting"), !value.has_value());
|
||||
for (size_t i = 0; i < options.size(); i++)
|
||||
{
|
||||
cd_options.emplace_back(translate_options ? Host::TranslateToString(tr_context, options[i]) :
|
||||
std::string(options[i]),
|
||||
(i == static_cast<size_t>(index)));
|
||||
}
|
||||
OpenChoiceDialog(title, false, std::move(cd_options),
|
||||
[game_settings, section = TinyString(section), key = TinyString(key),
|
||||
values](s32 index, const std::string& title, bool checked) {
|
||||
if (index >= 0)
|
||||
{
|
||||
auto lock = Host::GetSettingsLock();
|
||||
SettingsInterface* bsi = GetEditingSettingsInterface(game_settings);
|
||||
if (game_settings)
|
||||
{
|
||||
if (index == 0)
|
||||
bsi->DeleteValue(section, key);
|
||||
else
|
||||
bsi->SetIntValue(section, key, values[index - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
bsi->SetIntValue(section, key, values[index]);
|
||||
}
|
||||
|
||||
SetSettingsChanged(bsi);
|
||||
}
|
||||
|
||||
CloseChoiceDialog();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void FullscreenUI::DrawIntRangeSetting(SettingsInterface* bsi, const char* title, const char* summary,
|
||||
const char* section, const char* key, int default_value, int min_value,
|
||||
int max_value, const char* format, bool enabled, float height, ImFont* font,
|
||||
@ -3468,11 +3543,10 @@ void FullscreenUI::DrawConsoleSettingsPage()
|
||||
FSUI_NSTR("None (Double Speed)"), FSUI_NSTR("2x (Quad Speed)"), FSUI_NSTR("3x (6x Speed)"),
|
||||
FSUI_NSTR("4x (8x Speed)"), FSUI_NSTR("5x (10x Speed)"), FSUI_NSTR("6x (12x Speed)"),
|
||||
FSUI_NSTR("7x (14x Speed)"), FSUI_NSTR("8x (16x Speed)"), FSUI_NSTR("9x (18x Speed)"),
|
||||
FSUI_NSTR("10x (20x Speed)"),
|
||||
FSUI_NSTR("10x (20x Speed)"), FSUI_NSTR("Maximum"),
|
||||
};
|
||||
|
||||
static constexpr const std::array cdrom_seek_speeds = {
|
||||
FSUI_NSTR("Infinite/Instantaneous"),
|
||||
FSUI_NSTR("None (Normal Speed)"),
|
||||
FSUI_NSTR("2x"),
|
||||
FSUI_NSTR("3x"),
|
||||
@ -3483,8 +3557,11 @@ void FullscreenUI::DrawConsoleSettingsPage()
|
||||
FSUI_NSTR("8x"),
|
||||
FSUI_NSTR("9x"),
|
||||
FSUI_NSTR("10x"),
|
||||
FSUI_NSTR("Maximum"),
|
||||
};
|
||||
|
||||
static constexpr std::array cdrom_read_seek_speed_values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0};
|
||||
|
||||
SettingsInterface* bsi = GetEditingSettingsInterface();
|
||||
|
||||
BeginMenuButtons();
|
||||
@ -3541,12 +3618,12 @@ void FullscreenUI::DrawConsoleSettingsPage()
|
||||
bsi, FSUI_ICONSTR(ICON_FA_COMPACT_DISC, "Read Speedup"),
|
||||
FSUI_CSTR(
|
||||
"Speeds up CD-ROM reads by the specified factor. May improve loading speeds in some games, and break others."),
|
||||
"CDROM", "ReadSpeedup", 1, cdrom_read_speeds.data(), cdrom_read_speeds.size(), true, 1);
|
||||
"CDROM", "ReadSpeedup", 1, cdrom_read_speeds, true, cdrom_read_seek_speed_values);
|
||||
DrawIntListSetting(
|
||||
bsi, FSUI_ICONSTR(ICON_FA_SEARCH, "Seek Speedup"),
|
||||
FSUI_CSTR(
|
||||
"Speeds up CD-ROM seeks by the specified factor. May improve loading speeds in some games, and break others."),
|
||||
"CDROM", "SeekSpeedup", 1, cdrom_seek_speeds.data(), cdrom_seek_speeds.size(), true);
|
||||
"CDROM", "SeekSpeedup", 1, cdrom_seek_speeds, true, cdrom_read_seek_speed_values);
|
||||
|
||||
DrawIntRangeSetting(
|
||||
bsi, FSUI_ICONSTR(ICON_FA_FAST_FORWARD, "Readahead Sectors"),
|
||||
@ -8122,6 +8199,7 @@ TRANSLATE_NOOP("FullscreenUI", "Disabled");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Disables dithering and uses the full 8 bits per channel of color information.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Disc {} | {}");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Discord Server");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Displays DualShock/DualSense button icons in the footer and input binding, instead of Xbox buttons.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Displays popup messages on events such as achievement unlocks and leaderboard submissions.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Displays popup messages when starting, submitting, or failing a leaderboard challenge.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Double-Click Toggles Fullscreen");
|
||||
@ -8244,7 +8322,6 @@ TRANSLATE_NOOP("FullscreenUI", "Identifies any new files added to the game direc
|
||||
TRANSLATE_NOOP("FullscreenUI", "If not enabled, the current post processing chain will be ignored.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Increases the field of view from 4:3 to the chosen display aspect ratio in 3D games.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Increases the precision of polygon culling, reducing the number of holes in geometry.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Infinite/Instantaneous");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Inhibit Screensaver");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Input Sources");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Input profile '{}' loaded.");
|
||||
@ -8293,6 +8370,7 @@ TRANSLATE_NOOP("FullscreenUI", "Logs messages to the debug console where support
|
||||
TRANSLATE_NOOP("FullscreenUI", "Logs out of RetroAchievements.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Macro Button {}");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Makes games run closer to their console framerate, at a small cost to performance.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Maximum");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Memory Card Busy");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Memory Card Directory");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Memory Card Port {}");
|
||||
@ -8567,6 +8645,7 @@ TRANSLATE_NOOP("FullscreenUI", "Unknown File Size");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Unlimited");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Use Blit Swap Chain");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Use Debug GPU Device");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Use DualShock/DualSense Button Icons");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Use Global Setting");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Use Light Theme");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Use Old MDEC Routines");
|
||||
|
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#include "system.h"
|
||||
@ -4722,18 +4722,21 @@ void System::WarnAboutUnsafeSettings()
|
||||
g_settings.GetCPUOverclockPercent(), g_settings.cpu_overclock_numerator,
|
||||
g_settings.cpu_overclock_denominator);
|
||||
}
|
||||
if (g_settings.cdrom_read_speedup > 1)
|
||||
if (g_settings.cdrom_read_speedup != 1)
|
||||
{
|
||||
append_format(
|
||||
ICON_EMOJI_WARNING,
|
||||
TRANSLATE_FS("System", "CD-ROM read speedup set to {}x (effective speed {}x). This may crash games."),
|
||||
g_settings.cdrom_read_speedup, g_settings.cdrom_read_speedup * 2);
|
||||
TinyString speed;
|
||||
if (g_settings.cdrom_read_speedup == 0)
|
||||
speed = TRANSLATE_SV("System", "Maximum");
|
||||
else
|
||||
speed.format("{}x", g_settings.cdrom_read_speedup);
|
||||
append_format(ICON_EMOJI_WARNING,
|
||||
TRANSLATE_FS("System", "CD-ROM read speedup set to {}. This may crash games."), speed);
|
||||
}
|
||||
if (g_settings.cdrom_seek_speedup != 1)
|
||||
{
|
||||
TinyString speed;
|
||||
if (g_settings.cdrom_seek_speedup == 0)
|
||||
speed = TRANSLATE_SV("System", "Instant");
|
||||
speed = TRANSLATE_SV("System", "Maximum");
|
||||
else
|
||||
speed.format("{}x", g_settings.cdrom_seek_speedup);
|
||||
append_format(ICON_EMOJI_WARNING,
|
||||
|
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#include "consolesettingswidget.h"
|
||||
@ -14,6 +14,8 @@
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
static constexpr const int CDROM_SPEEDUP_VALUES[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0};
|
||||
|
||||
ConsoleSettingsWidget::ConsoleSettingsWidget(SettingsWindow* dialog, QWidget* parent)
|
||||
: QWidget(parent), m_dialog(dialog)
|
||||
{
|
||||
@ -64,8 +66,10 @@ ConsoleSettingsWidget::ConsoleSettingsWidget(SettingsWindow* dialog, QWidget* pa
|
||||
m_ui.cdromIgnoreDriveSubcode->setEnabled(false);
|
||||
}
|
||||
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cdromSeekSpeedup, "CDROM", "SeekSpeedup", 1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cdromReadSpeedup, "CDROM", "ReadSpeedup", 1, 1);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cdromSeekSpeedup, "CDROM", "SeekSpeedup", 1,
|
||||
CDROM_SPEEDUP_VALUES);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cdromReadSpeedup, "CDROM", "ReadSpeedup", 1,
|
||||
CDROM_SPEEDUP_VALUES);
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.region, tr("Region"), tr("Auto-Detect"),
|
||||
tr("Determines the emulated hardware type."));
|
||||
|
@ -207,6 +207,11 @@
|
||||
<string>10x (20x Speed)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Maximum</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
@ -221,11 +226,6 @@
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Infinite/Instantaneous</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None (Normal Speed)</string>
|
||||
@ -276,6 +276,11 @@
|
||||
<string>10x</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Maximum</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
|
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#pragma once
|
||||
@ -29,8 +29,10 @@
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QSlider>
|
||||
#include <QtWidgets/QSpinBox>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <type_traits>
|
||||
|
||||
namespace SettingWidgetBinder {
|
||||
@ -790,6 +792,57 @@ static void BindWidgetToIntSetting(SettingsInterface* sif, WidgetType* widget, s
|
||||
}
|
||||
}
|
||||
|
||||
template<typename WidgetType>
|
||||
static void BindWidgetToIntSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key,
|
||||
int default_value, std::span<const int> values)
|
||||
{
|
||||
using Accessor = SettingAccessor<WidgetType>;
|
||||
|
||||
static constexpr auto value_to_index = [](s32 value, const std::span<const int> values) {
|
||||
for (size_t i = 0; i < values.size(); i++)
|
||||
{
|
||||
if (values[i] == value)
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
const s32 value = Host::GetBaseIntSettingValue(section.c_str(), key.c_str(), static_cast<s32>(default_value));
|
||||
|
||||
if (sif)
|
||||
{
|
||||
Accessor::makeNullableInt(widget, value);
|
||||
|
||||
int sif_value;
|
||||
if (sif->GetIntValue(section.c_str(), key.c_str(), &sif_value))
|
||||
Accessor::setNullableIntValue(widget, value_to_index(sif_value, values));
|
||||
else
|
||||
Accessor::setNullableIntValue(widget, std::nullopt);
|
||||
|
||||
Accessor::connectValueChanged(widget, [sif, widget, section = std::move(section), key = std::move(key), values]() {
|
||||
if (std::optional<int> new_value = Accessor::getNullableIntValue(widget); new_value.has_value())
|
||||
sif->SetIntValue(section.c_str(), key.c_str(), values[new_value.value()]);
|
||||
else
|
||||
sif->DeleteValue(section.c_str(), key.c_str());
|
||||
|
||||
QtHost::SaveGameSettings(sif, true);
|
||||
g_emu_thread->reloadGameSettings();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Accessor::setIntValue(widget, value_to_index(value, values));
|
||||
|
||||
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), values]() {
|
||||
const int new_value = Accessor::getIntValue(widget);
|
||||
Host::SetBaseIntSettingValue(section.c_str(), key.c_str(), values[new_value]);
|
||||
Host::CommitBaseSettingChanges();
|
||||
g_emu_thread->applySettings();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template<typename WidgetType>
|
||||
static inline void BindWidgetAndLabelToIntSetting(SettingsInterface* sif, WidgetType* widget, QLabel* label,
|
||||
const QString& label_suffix, std::string section, std::string key,
|
||||
|
Loading…
x
Reference in New Issue
Block a user