mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 07:35:41 +00:00
CDROM: Add timing for speed changes/adjust seek timing
This makes the BIOS take longer to load the executable off the disc, giving the sound effects longer to fade out and reducing the overlap with the game.
This commit is contained in:
parent
809b9f89ca
commit
05e4e7d262
|
@ -50,6 +50,7 @@ void CDROM::SoftReset()
|
|||
m_secondary_status.bits = 0;
|
||||
m_secondary_status.motor_on = HasMedia();
|
||||
m_mode.bits = 0;
|
||||
m_current_double_speed = false;
|
||||
m_interrupt_enable_register = INTERRUPT_REGISTER_MASK;
|
||||
m_interrupt_flag_register = 0;
|
||||
m_pending_async_interrupt = 0;
|
||||
|
@ -111,6 +112,7 @@ bool CDROM::DoState(StateWrapper& sw)
|
|||
sw.Do(&m_status.bits);
|
||||
sw.Do(&m_secondary_status.bits);
|
||||
sw.Do(&m_mode.bits);
|
||||
sw.Do(&m_current_double_speed);
|
||||
sw.Do(&m_interrupt_enable_register);
|
||||
sw.Do(&m_interrupt_flag_register);
|
||||
sw.Do(&m_pending_async_interrupt);
|
||||
|
@ -526,7 +528,7 @@ void CDROM::UpdateInterruptRequest()
|
|||
m_interrupt_controller->InterruptRequest(InterruptController::IRQ::CDROM);
|
||||
}
|
||||
|
||||
TickCount CDROM::GetAckDelayForCommand(Command command) const
|
||||
TickCount CDROM::GetAckDelayForCommand(Command command)
|
||||
{
|
||||
if (command == Command::Init)
|
||||
{
|
||||
|
@ -541,27 +543,36 @@ TickCount CDROM::GetAckDelayForCommand(Command command) const
|
|||
return HasMedia() ? default_ack_delay_with_disc : default_ack_delay_no_disc;
|
||||
}
|
||||
|
||||
TickCount CDROM::GetTicksForRead() const
|
||||
TickCount CDROM::GetTicksForRead()
|
||||
{
|
||||
return m_mode.double_speed ? (MASTER_CLOCK / 150) : (MASTER_CLOCK / 75);
|
||||
}
|
||||
|
||||
TickCount CDROM::GetTicksForSeek() const
|
||||
TickCount CDROM::GetTicksForSeek(CDImage::LBA new_lba)
|
||||
{
|
||||
const CDImage::LBA current_lba = m_secondary_status.motor_on ? m_reader.GetLastReadSector() : 0;
|
||||
const CDImage::LBA new_lba = m_setloc_position.ToLBA();
|
||||
const CDImage::LBA current_lba = m_secondary_status.motor_on ? m_last_requested_sector : 0;
|
||||
const u32 lba_diff = static_cast<u32>((new_lba > current_lba) ? (new_lba - current_lba) : (current_lba - new_lba));
|
||||
|
||||
// const TickCount ticks = static_cast<TickCount>(20000 + lba_diff * 100);
|
||||
|
||||
// Formula from Mednafen.
|
||||
TickCount ticks = std::max<TickCount>(20000, lba_diff * MASTER_CLOCK * 1000 / (72 * 60 * 75) / 1000);
|
||||
if (!m_secondary_status.motor_on)
|
||||
ticks += MASTER_CLOCK;
|
||||
else if (m_drive_state == DriveState::Idle) // paused
|
||||
ticks += 1237952 << (BoolToUInt8(!m_mode.double_speed));
|
||||
if (lba_diff >= 2550)
|
||||
ticks += static_cast<TickCount>(u64(MASTER_CLOCK) * 300 / 1000);
|
||||
else if (m_drive_state == DriveState::Idle) // paused
|
||||
ticks += 1237952 << (BoolToUInt8(!m_mode.double_speed));
|
||||
else if (lba_diff >= 3 && lba_diff < 12)
|
||||
ticks += MASTER_CLOCK / (75 << (BoolToUInt8(!m_mode.double_speed)) << 2);
|
||||
|
||||
if (m_mode.double_speed != m_current_double_speed)
|
||||
{
|
||||
Log_DevPrintf("Switched from %s to %s speed", m_current_double_speed ? "double" : "single",
|
||||
m_mode.double_speed ? "double" : "single");
|
||||
m_current_double_speed = m_mode.double_speed;
|
||||
|
||||
// Approximate time for the motor to change speed?
|
||||
ticks += static_cast<u32>(static_cast<double>(MASTER_CLOCK) * 1.5);
|
||||
}
|
||||
|
||||
Log_DevPrintf("Seek time for %u LBAs: %d", lba_diff, ticks);
|
||||
return ticks;
|
||||
|
@ -631,7 +642,7 @@ void CDROM::ExecuteCommand()
|
|||
SendACKAndStat();
|
||||
|
||||
m_drive_state = DriveState::ReadingID;
|
||||
m_drive_event->Schedule(18000);
|
||||
m_drive_event->Schedule(GetTicksForSeek(0) + GetTicksForRead());
|
||||
|
||||
EndCommand();
|
||||
return;
|
||||
|
@ -818,7 +829,7 @@ void CDROM::ExecuteCommand()
|
|||
SendACKAndStat();
|
||||
|
||||
m_drive_state = DriveState::Resetting;
|
||||
m_drive_event->Schedule(80000);
|
||||
m_drive_event->Schedule(400000);
|
||||
|
||||
EndCommand();
|
||||
return;
|
||||
|
@ -837,7 +848,7 @@ void CDROM::ExecuteCommand()
|
|||
SendACKAndStat();
|
||||
|
||||
m_drive_state = DriveState::Resetting;
|
||||
m_drive_event->Schedule(80000);
|
||||
m_drive_event->Schedule(MASTER_CLOCK);
|
||||
}
|
||||
|
||||
EndCommand();
|
||||
|
@ -1218,7 +1229,8 @@ void CDROM::BeginSeeking(bool logical, bool read_after_seek, bool play_after_see
|
|||
Log_DebugPrintf("Seeking to [%02u:%02u:%02u] (LBA %u) (%s)", m_setloc_position.minute, m_setloc_position.second,
|
||||
m_setloc_position.frame, m_setloc_position.ToLBA(), logical ? "logical" : "physical");
|
||||
|
||||
const TickCount seek_time = GetTicksForSeek();
|
||||
const CDImage::LBA seek_lba = m_setloc_position.ToLBA();
|
||||
const TickCount seek_time = GetTicksForSeek(seek_lba);
|
||||
|
||||
m_secondary_status.ClearActiveBits();
|
||||
m_secondary_status.motor_on = true;
|
||||
|
@ -1227,7 +1239,7 @@ void CDROM::BeginSeeking(bool logical, bool read_after_seek, bool play_after_see
|
|||
m_drive_state = logical ? DriveState::SeekingLogical : DriveState::SeekingPhysical;
|
||||
m_drive_event->SetIntervalAndSchedule(seek_time);
|
||||
|
||||
m_last_requested_sector = m_setloc_position.ToLBA();
|
||||
m_last_requested_sector = seek_lba;
|
||||
m_reader.QueueReadSector(m_last_requested_sector);
|
||||
}
|
||||
|
||||
|
@ -1394,12 +1406,19 @@ void CDROM::DoIDRead()
|
|||
{
|
||||
flags_byte |= (1 << 6); // Disc Missing
|
||||
}
|
||||
else if (m_system->GetSettings().cdrom_region_check &&
|
||||
(m_disc_region == DiscRegion::Other ||
|
||||
m_system->GetRegion() != System::GetConsoleRegionForDiscRegion(m_disc_region)))
|
||||
else
|
||||
{
|
||||
stat_byte |= STAT_ID_ERROR;
|
||||
flags_byte |= (1 << 7); // Unlicensed
|
||||
// this is where it would get read from the start of the disc?
|
||||
m_last_requested_sector = 0;
|
||||
m_reader.QueueReadSector(m_last_requested_sector);
|
||||
|
||||
if (m_system->GetSettings().cdrom_region_check &&
|
||||
(m_disc_region == DiscRegion::Other ||
|
||||
m_system->GetRegion() != System::GetConsoleRegionForDiscRegion(m_disc_region)))
|
||||
{
|
||||
stat_byte |= STAT_ID_ERROR;
|
||||
flags_byte |= (1 << 7); // Unlicensed
|
||||
}
|
||||
}
|
||||
|
||||
m_async_response_fifo.Clear();
|
||||
|
|
|
@ -210,9 +210,9 @@ private:
|
|||
void UpdateStatusRegister();
|
||||
void UpdateInterruptRequest();
|
||||
|
||||
TickCount GetAckDelayForCommand(Command command) const;
|
||||
TickCount GetTicksForRead() const;
|
||||
TickCount GetTicksForSeek() const;
|
||||
TickCount GetAckDelayForCommand(Command command);
|
||||
TickCount GetTicksForRead();
|
||||
TickCount GetTicksForSeek(CDImage::LBA new_lba);
|
||||
void BeginCommand(Command command); // also update status register
|
||||
void EndCommand(); // also updates status register
|
||||
void AbortCommand();
|
||||
|
@ -253,6 +253,7 @@ private:
|
|||
StatusRegister m_status = {};
|
||||
SecondaryStatusRegister m_secondary_status = {};
|
||||
ModeRegister m_mode = {};
|
||||
bool m_current_double_speed = false;
|
||||
|
||||
u8 m_interrupt_enable_register = INTERRUPT_REGISTER_MASK;
|
||||
u8 m_interrupt_flag_register = 0;
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
#include "types.h"
|
||||
|
||||
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
|
||||
static constexpr u32 SAVE_STATE_VERSION = 21;
|
||||
static constexpr u32 SAVE_STATE_VERSION = 22;
|
||||
|
|
Loading…
Reference in a new issue