CDROM: Fix integer overflow in seek timing calculation

This commit is contained in:
Connor McLaughlin 2020-06-01 22:20:26 +10:00
parent 1947080d91
commit 5e7fd5aa71

View file

@ -818,13 +818,21 @@ TickCount CDROM::GetTicksForSeek(CDImage::LBA new_lba)
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. // Formula from Mednafen.
TickCount ticks = std::max<TickCount>(20000, lba_diff * MASTER_CLOCK * 1000 / (72 * 60 * 75) / 1000); TickCount ticks = std::max<TickCount>(
20000, static_cast<u32>(
((static_cast<u64>(lba_diff) * static_cast<u64>(MASTER_CLOCK) * static_cast<u64>(1000)) / (72 * 60 * 75)) /
1000));
if (!m_secondary_status.motor_on) if (!m_secondary_status.motor_on)
ticks += MASTER_CLOCK; ticks += MASTER_CLOCK;
if (lba_diff >= 2550) if (lba_diff >= 2550)
ticks += static_cast<TickCount>(u64(MASTER_CLOCK) * 300 / 1000); ticks += static_cast<TickCount>(u64(MASTER_CLOCK) * 300 / 1000);
else if (m_drive_state == DriveState::Idle) // paused else if (m_drive_state == DriveState::Idle) // paused
ticks += 1237952 << (BoolToUInt8(!m_mode.double_speed)); {
// 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
// it's probably closer.
ticks += GetTicksForRead() * 4u;
}
if (m_mode.double_speed != m_current_double_speed) if (m_mode.double_speed != m_current_double_speed)
{ {
@ -836,10 +844,6 @@ TickCount CDROM::GetTicksForSeek(CDImage::LBA new_lba)
ticks += static_cast<u32>(static_cast<double>(MASTER_CLOCK) * 0.1); ticks += static_cast<u32>(static_cast<double>(MASTER_CLOCK) * 0.1);
} }
// it's unlikely that the drive would seek to exactly the correct position, so simulate this by adding the time
// required to read a few sectors
ticks += GetTicksForRead() * 4u;
Log_DevPrintf("Seek time for %u LBAs: %d", lba_diff, ticks); Log_DevPrintf("Seek time for %u LBAs: %d", lba_diff, ticks);
return ticks; return ticks;
} }