mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 14:25:37 +00:00
CDROM: Add seek speedup enhancement
This commit is contained in:
parent
143a82b543
commit
98e4c181ca
|
@ -684,24 +684,30 @@ TickCount CDROM::GetTicksForRead()
|
||||||
|
|
||||||
TickCount CDROM::GetTicksForSeek(CDImage::LBA new_lba)
|
TickCount CDROM::GetTicksForSeek(CDImage::LBA new_lba)
|
||||||
{
|
{
|
||||||
|
static constexpr TickCount MIN_TICKS = 20000;
|
||||||
|
|
||||||
|
if (g_settings.cdrom_seek_speedup == 0)
|
||||||
|
return MIN_TICKS;
|
||||||
|
|
||||||
const TickCount tps = System::GetTicksPerSecond();
|
const TickCount tps = System::GetTicksPerSecond();
|
||||||
const CDImage::LBA current_lba = m_secondary_status.motor_on ? m_current_lba : 0;
|
const CDImage::LBA current_lba = m_secondary_status.motor_on ? m_current_lba : 0;
|
||||||
const u32 lba_diff = static_cast<u32>((new_lba > current_lba) ? (new_lba - current_lba) : (current_lba - new_lba));
|
const u32 lba_diff = static_cast<u32>((new_lba > current_lba) ? (new_lba - current_lba) : (current_lba - new_lba));
|
||||||
|
|
||||||
// Formula from Mednafen.
|
// Original formula based on Mednafen. Still not accurate, doesn't consider the varying number of sectors per track.
|
||||||
TickCount ticks = std::max<TickCount>(
|
// TODO: Replace with algorithm based on mechacon behavior.
|
||||||
|
u32 ticks = std::max<u32>(
|
||||||
20000, static_cast<u32>(
|
20000, static_cast<u32>(
|
||||||
((static_cast<u64>(lba_diff) * static_cast<u64>(tps) * static_cast<u64>(1000)) / (72 * 60 * 75)) / 1000));
|
((static_cast<u64>(lba_diff) * static_cast<u64>(tps) * static_cast<u64>(1000)) / (72 * 60 * 75)) / 1000));
|
||||||
if (!m_secondary_status.motor_on)
|
if (!m_secondary_status.motor_on)
|
||||||
ticks += tps;
|
ticks += tps;
|
||||||
if (lba_diff >= 2550)
|
if (lba_diff >= 2550)
|
||||||
ticks += static_cast<TickCount>((u64(tps) * 300) / 1000);
|
ticks += static_cast<u32>((u64(tps) * 300) / 1000);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// When paused, the CDC seems to keep reading the disc until it hits the position it's set to, then skip 10-15
|
// When paused, the CDC seems to keep reading the disc until it hits the position it's set to, then skip 10-15
|
||||||
// sectors back (depending on how far into the disc it is). We'll be generous and use 4 sectors, since on average
|
// sectors back (depending on how far into the disc it is). We'll be generous and use 4 sectors, since on average
|
||||||
// it's probably closer.
|
// it's probably closer.
|
||||||
ticks += GetTicksForRead() * 4u;
|
ticks += static_cast<u32>(GetTicksForRead()) * 4u;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_mode.double_speed != m_current_double_speed)
|
if (m_mode.double_speed != m_current_double_speed)
|
||||||
|
@ -714,8 +720,11 @@ TickCount CDROM::GetTicksForSeek(CDImage::LBA new_lba)
|
||||||
ticks += static_cast<u32>(static_cast<double>(tps) * 0.1);
|
ticks += static_cast<u32>(static_cast<double>(tps) * 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log_DevPrintf("Seek time for %u LBAs: %d", lba_diff, ticks);
|
if (g_settings.cdrom_seek_speedup > 1)
|
||||||
return ticks;
|
ticks = std::min<u32>(ticks / g_settings.cdrom_seek_speedup, MIN_TICKS);
|
||||||
|
|
||||||
|
Log_DevPrintf("Seek time for %u LBAs: %u", lba_diff, ticks);
|
||||||
|
return static_cast<u32>(ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
TickCount CDROM::GetTicksForStop(bool motor_was_on)
|
TickCount CDROM::GetTicksForStop(bool motor_was_on)
|
||||||
|
|
|
@ -558,6 +558,7 @@ void HostInterface::SetDefaultSettings(SettingsInterface& si)
|
||||||
si.SetBoolValue("CDROM", "LoadImageToRAM", false);
|
si.SetBoolValue("CDROM", "LoadImageToRAM", false);
|
||||||
si.SetBoolValue("CDROM", "MuteCDAudio", false);
|
si.SetBoolValue("CDROM", "MuteCDAudio", false);
|
||||||
si.SetIntValue("CDROM", "ReadSpeedup", 1);
|
si.SetIntValue("CDROM", "ReadSpeedup", 1);
|
||||||
|
si.SetIntValue("CDROM", "SeekSpeedup", 1);
|
||||||
|
|
||||||
si.SetStringValue("Audio", "Backend", Settings::GetAudioBackendName(Settings::DEFAULT_AUDIO_BACKEND));
|
si.SetStringValue("Audio", "Backend", Settings::GetAudioBackendName(Settings::DEFAULT_AUDIO_BACKEND));
|
||||||
si.SetIntValue("Audio", "OutputVolume", 100);
|
si.SetIntValue("Audio", "OutputVolume", 100);
|
||||||
|
@ -638,7 +639,8 @@ void HostInterface::FixIncompatibleSettings(bool display_osd_messages)
|
||||||
g_settings.gpu_widescreen_hack = false;
|
g_settings.gpu_widescreen_hack = false;
|
||||||
g_settings.gpu_pgxp_enable = false;
|
g_settings.gpu_pgxp_enable = false;
|
||||||
g_settings.gpu_24bit_chroma_smoothing = false;
|
g_settings.gpu_24bit_chroma_smoothing = false;
|
||||||
g_settings.cdrom_read_speedup = false;
|
g_settings.cdrom_read_speedup = 1;
|
||||||
|
g_settings.cdrom_seek_speedup = 1;
|
||||||
g_settings.cdrom_mute_cd_audio = false;
|
g_settings.cdrom_mute_cd_audio = false;
|
||||||
g_settings.texture_replacements.enable_vram_write_replacements = false;
|
g_settings.texture_replacements.enable_vram_write_replacements = false;
|
||||||
g_settings.bios_patch_fast_boot = false;
|
g_settings.bios_patch_fast_boot = false;
|
||||||
|
|
|
@ -255,6 +255,7 @@ void Settings::Load(SettingsInterface& si)
|
||||||
cdrom_load_image_to_ram = si.GetBoolValue("CDROM", "LoadImageToRAM", false);
|
cdrom_load_image_to_ram = si.GetBoolValue("CDROM", "LoadImageToRAM", false);
|
||||||
cdrom_mute_cd_audio = si.GetBoolValue("CDROM", "MuteCDAudio", false);
|
cdrom_mute_cd_audio = si.GetBoolValue("CDROM", "MuteCDAudio", false);
|
||||||
cdrom_read_speedup = si.GetIntValue("CDROM", "ReadSpeedup", 1);
|
cdrom_read_speedup = si.GetIntValue("CDROM", "ReadSpeedup", 1);
|
||||||
|
cdrom_seek_speedup = si.GetIntValue("CDROM", "SeekSpeedup", 1);
|
||||||
|
|
||||||
audio_backend =
|
audio_backend =
|
||||||
ParseAudioBackend(si.GetStringValue("Audio", "Backend", GetAudioBackendName(DEFAULT_AUDIO_BACKEND)).c_str())
|
ParseAudioBackend(si.GetStringValue("Audio", "Backend", GetAudioBackendName(DEFAULT_AUDIO_BACKEND)).c_str())
|
||||||
|
@ -430,6 +431,7 @@ void Settings::Save(SettingsInterface& si) const
|
||||||
si.SetBoolValue("CDROM", "LoadImageToRAM", cdrom_load_image_to_ram);
|
si.SetBoolValue("CDROM", "LoadImageToRAM", cdrom_load_image_to_ram);
|
||||||
si.SetBoolValue("CDROM", "MuteCDAudio", cdrom_mute_cd_audio);
|
si.SetBoolValue("CDROM", "MuteCDAudio", cdrom_mute_cd_audio);
|
||||||
si.SetIntValue("CDROM", "ReadSpeedup", cdrom_read_speedup);
|
si.SetIntValue("CDROM", "ReadSpeedup", cdrom_read_speedup);
|
||||||
|
si.SetIntValue("CDROM", "SeekSpeedup", cdrom_seek_speedup);
|
||||||
|
|
||||||
si.SetStringValue("Audio", "Backend", GetAudioBackendName(audio_backend));
|
si.SetStringValue("Audio", "Backend", GetAudioBackendName(audio_backend));
|
||||||
si.SetIntValue("Audio", "OutputVolume", audio_output_volume);
|
si.SetIntValue("Audio", "OutputVolume", audio_output_volume);
|
||||||
|
|
|
@ -156,6 +156,7 @@ struct Settings
|
||||||
bool cdrom_load_image_to_ram = false;
|
bool cdrom_load_image_to_ram = false;
|
||||||
bool cdrom_mute_cd_audio = false;
|
bool cdrom_mute_cd_audio = false;
|
||||||
u32 cdrom_read_speedup = 1;
|
u32 cdrom_read_speedup = 1;
|
||||||
|
u32 cdrom_seek_speedup = 1;
|
||||||
|
|
||||||
AudioBackend audio_backend = AudioBackend::Cubeb;
|
AudioBackend audio_backend = AudioBackend::Cubeb;
|
||||||
s32 audio_output_volume = 100;
|
s32 audio_output_volume = 100;
|
||||||
|
|
|
@ -885,10 +885,12 @@ bool Initialize(bool force_software_renderer)
|
||||||
g_mdec.Initialize();
|
g_mdec.Initialize();
|
||||||
g_sio.Initialize();
|
g_sio.Initialize();
|
||||||
|
|
||||||
|
static constexpr float WARNING_DURATION = 15.0f;
|
||||||
|
|
||||||
if (g_settings.cpu_overclock_active)
|
if (g_settings.cpu_overclock_active)
|
||||||
{
|
{
|
||||||
g_host_interface->AddFormattedOSDMessage(
|
g_host_interface->AddFormattedOSDMessage(
|
||||||
10.0f,
|
WARNING_DURATION,
|
||||||
g_host_interface->TranslateString("OSDMessage",
|
g_host_interface->TranslateString("OSDMessage",
|
||||||
"CPU clock speed is set to %u%% (%u / %u). This may result in instability."),
|
"CPU clock speed is set to %u%% (%u / %u). This may result in instability."),
|
||||||
g_settings.GetCPUOverclockPercent(), g_settings.cpu_overclock_numerator, g_settings.cpu_overclock_denominator);
|
g_settings.GetCPUOverclockPercent(), g_settings.cpu_overclock_numerator, g_settings.cpu_overclock_denominator);
|
||||||
|
@ -896,11 +898,29 @@ bool Initialize(bool force_software_renderer)
|
||||||
if (g_settings.cdrom_read_speedup > 1)
|
if (g_settings.cdrom_read_speedup > 1)
|
||||||
{
|
{
|
||||||
g_host_interface->AddFormattedOSDMessage(
|
g_host_interface->AddFormattedOSDMessage(
|
||||||
10.0f,
|
WARNING_DURATION,
|
||||||
g_host_interface->TranslateString(
|
g_host_interface->TranslateString(
|
||||||
"OSDMessage", "CD-ROM read speedup set to %ux (effective speed %ux). This may result in instability."),
|
"OSDMessage", "CD-ROM read speedup set to %ux (effective speed %ux). This may result in instability."),
|
||||||
g_settings.cdrom_read_speedup, g_settings.cdrom_read_speedup * 2);
|
g_settings.cdrom_read_speedup, g_settings.cdrom_read_speedup * 2);
|
||||||
}
|
}
|
||||||
|
if (g_settings.cdrom_seek_speedup != 1)
|
||||||
|
{
|
||||||
|
if (g_settings.cdrom_seek_speedup == 0)
|
||||||
|
{
|
||||||
|
g_host_interface->AddOSDMessage(
|
||||||
|
g_host_interface->TranslateStdString("OSDMessage",
|
||||||
|
"CD-ROM seek speedup set to instant. This may result in instability."),
|
||||||
|
WARNING_DURATION);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_host_interface->AddFormattedOSDMessage(
|
||||||
|
WARNING_DURATION,
|
||||||
|
g_host_interface->TranslateString("OSDMessage",
|
||||||
|
"CD-ROM seek speedup set to %ux. This may result in instability."),
|
||||||
|
g_settings.cdrom_seek_speedup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UpdateThrottlePeriod();
|
UpdateThrottlePeriod();
|
||||||
UpdateMemorySaveStateSettings();
|
UpdateMemorySaveStateSettings();
|
||||||
|
|
|
@ -41,6 +41,7 @@ ConsoleSettingsWidget::ConsoleSettingsWidget(QtHostInterface* host_interface, QW
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.cdromRegionCheck, "CDROM", "RegionCheck", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.cdromRegionCheck, "CDROM", "RegionCheck", false);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.cdromLoadImageToRAM, "CDROM", "LoadImageToRAM",
|
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.cdromLoadImageToRAM, "CDROM", "LoadImageToRAM",
|
||||||
false);
|
false);
|
||||||
|
SettingWidgetBinder::BindWidgetToIntSetting(m_host_interface, m_ui.cdromSeekSpeedup, "CDROM", "SeekSpeedup", 1);
|
||||||
SettingWidgetBinder::BindWidgetToEnumSetting(m_host_interface, m_ui.multitapMode, "ControllerPorts", "MultitapMode",
|
SettingWidgetBinder::BindWidgetToEnumSetting(m_host_interface, m_ui.multitapMode, "ControllerPorts", "MultitapMode",
|
||||||
&Settings::ParseMultitapModeName, &Settings::GetMultitapModeName,
|
&Settings::ParseMultitapModeName, &Settings::GetMultitapModeName,
|
||||||
Settings::DEFAULT_MULTITAP_MODE);
|
Settings::DEFAULT_MULTITAP_MODE);
|
||||||
|
@ -67,6 +68,10 @@ ConsoleSettingsWidget::ConsoleSettingsWidget(QtHostInterface* host_interface, QW
|
||||||
m_ui.cdromReadSpeedup, tr("CDROM Read Speedup"), tr("None (Double Speed)"),
|
m_ui.cdromReadSpeedup, tr("CDROM Read Speedup"), tr("None (Double Speed)"),
|
||||||
tr("Speeds up CD-ROM reads by the specified factor. Only applies to double-speed reads, and is ignored when audio "
|
tr("Speeds up CD-ROM reads by the specified factor. Only applies to double-speed reads, and is ignored when audio "
|
||||||
"is playing. May improve loading speeds in some games, at the cost of breaking others."));
|
"is playing. May improve loading speeds in some games, at the cost of breaking others."));
|
||||||
|
dialog->registerWidgetHelp(
|
||||||
|
m_ui.cdromReadSpeedup, tr("CDROM Seek Speedup"), tr("None (Normal Speed)"),
|
||||||
|
tr("Reduces the simulated time for the CD-ROM sled to move to different areas of the disc. Can improve loading "
|
||||||
|
"times, but crash games which do not expect the CD-ROM to operate faster."));
|
||||||
dialog->registerWidgetHelp(
|
dialog->registerWidgetHelp(
|
||||||
m_ui.cdromReadThread, tr("Use Read Thread (Asynchronous)"), tr("Checked"),
|
m_ui.cdromReadThread, tr("Use Read Thread (Asynchronous)"), tr("Checked"),
|
||||||
tr("Reduces hitches in emulation by reading/decompressing CD data asynchronously on a worker thread."));
|
tr("Reduces hitches in emulation by reading/decompressing CD data asynchronously on a worker thread."));
|
||||||
|
|
|
@ -198,7 +198,7 @@
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0" colspan="2">
|
<item row="2" column="0" colspan="2">
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QCheckBox" name="cdromReadThread">
|
<widget class="QCheckBox" name="cdromReadThread">
|
||||||
|
@ -223,6 +223,75 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Seek Speedup:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QComboBox" name="cdromSeekSpeedup">
|
||||||
|
<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>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>2x</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>3x</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>4x</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>5x</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>6x</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>7x</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>8x</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>9x</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>10x</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -1425,6 +1425,9 @@ void DrawSettingsWindow()
|
||||||
make_array("None (Double Speed)", "2x (Quad Speed)", "3x (6x Speed)", "4x (8x Speed)", "5x (10x Speed)",
|
make_array("None (Double Speed)", "2x (Quad Speed)", "3x (6x Speed)", "4x (8x Speed)", "5x (10x Speed)",
|
||||||
"6x (12x Speed)", "7x (14x Speed)", "8x (16x Speed)", "9x (18x Speed)", "10x (20x Speed)");
|
"6x (12x Speed)", "7x (14x Speed)", "8x (16x Speed)", "9x (18x Speed)", "10x (20x Speed)");
|
||||||
|
|
||||||
|
static constexpr auto cdrom_seek_speeds = make_array("Infinite/Instantaneous", "None (Normal Speed)", "2x",
|
||||||
|
"3x", "4x", "5x", "6x", "7x", "8x", "9x", "10x");
|
||||||
|
|
||||||
BeginMenuButtons();
|
BeginMenuButtons();
|
||||||
|
|
||||||
MenuHeading("Console Settings");
|
MenuHeading("Console Settings");
|
||||||
|
@ -1456,7 +1459,7 @@ void DrawSettingsWindow()
|
||||||
MenuHeading("CD-ROM Emulation");
|
MenuHeading("CD-ROM Emulation");
|
||||||
|
|
||||||
const u32 read_speed_index =
|
const u32 read_speed_index =
|
||||||
std::min(s_settings_copy.cdrom_read_speedup, static_cast<u32>(cdrom_read_speeds.size() + 1)) - 1;
|
std::clamp<u32>(s_settings_copy.cdrom_read_speedup, 1u, static_cast<u32>(cdrom_read_speeds.size())) - 1u;
|
||||||
if (MenuButtonWithValue("Read Speedup",
|
if (MenuButtonWithValue("Read Speedup",
|
||||||
"Speeds up CD-ROM reads by the specified factor. May improve loading speeds in some "
|
"Speeds up CD-ROM reads by the specified factor. May improve loading speeds in some "
|
||||||
"games, and break others.",
|
"games, and break others.",
|
||||||
|
@ -1474,6 +1477,25 @@ void DrawSettingsWindow()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const u32 seek_speed_index =
|
||||||
|
std::min(s_settings_copy.cdrom_seek_speedup, static_cast<u32>(cdrom_seek_speeds.size()));
|
||||||
|
if (MenuButtonWithValue("Seek Speedup",
|
||||||
|
"Speeds up CD-ROM seeks by the specified factor. May improve loading speeds in some "
|
||||||
|
"games, and break others.",
|
||||||
|
cdrom_seek_speeds[seek_speed_index]))
|
||||||
|
{
|
||||||
|
ImGuiFullscreen::ChoiceDialogOptions options;
|
||||||
|
options.reserve(cdrom_seek_speeds.size());
|
||||||
|
for (u32 i = 0; i < static_cast<u32>(cdrom_seek_speeds.size()); i++)
|
||||||
|
options.emplace_back(cdrom_seek_speeds[i], i == seek_speed_index);
|
||||||
|
OpenChoiceDialog("CD-ROM Seek Speedup", false, std::move(options),
|
||||||
|
[](s32 index, const std::string& title, bool checked) {
|
||||||
|
if (index >= 0)
|
||||||
|
s_settings_copy.cdrom_seek_speedup = static_cast<u32>(index);
|
||||||
|
CloseChoiceDialog();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
settings_changed |= ToggleButton(
|
settings_changed |= ToggleButton(
|
||||||
"Enable Read Thread",
|
"Enable Read Thread",
|
||||||
"Reduces hitches in emulation by reading/decompressing CD data asynchronously on a worker thread.",
|
"Reduces hitches in emulation by reading/decompressing CD data asynchronously on a worker thread.",
|
||||||
|
|
Loading…
Reference in a new issue