From 05e4e7d262c7564673bdc57cc78d9f8e292bbb85 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 11 Apr 2020 00:40:39 +1000 Subject: [PATCH] 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. --- src/core/cdrom.cpp | 57 +++++++++++++++++++++++------------ src/core/cdrom.h | 7 +++-- src/core/save_state_version.h | 2 +- 3 files changed, 43 insertions(+), 23 deletions(-) diff --git a/src/core/cdrom.cpp b/src/core/cdrom.cpp index 81400fc3c..f79a207b7 100644 --- a/src/core/cdrom.cpp +++ b/src/core/cdrom.cpp @@ -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((new_lba > current_lba) ? (new_lba - current_lba) : (current_lba - new_lba)); - // const TickCount ticks = static_cast(20000 + lba_diff * 100); - // Formula from Mednafen. TickCount ticks = std::max(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(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(static_cast(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(); diff --git a/src/core/cdrom.h b/src/core/cdrom.h index 4f7a35324..414013f6f 100644 --- a/src/core/cdrom.h +++ b/src/core/cdrom.h @@ -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; diff --git a/src/core/save_state_version.h b/src/core/save_state_version.h index f7193a1bd..5f883c3c4 100644 --- a/src/core/save_state_version.h +++ b/src/core/save_state_version.h @@ -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;