CDROM: Simulate motor spin-up time

Fixes disc changing in Tales of Destiny II.
This commit is contained in:
Connor McLaughlin 2021-06-11 20:19:17 +10:00
parent 95247b0b5e
commit 9d36ce757d
2 changed files with 37 additions and 6 deletions

View file

@ -276,7 +276,10 @@ void CDROM::InsertMedia(std::unique_ptr<CDImage> media)
// motor automatically spins up // motor automatically spins up
if (m_drive_state != DriveState::ShellOpening) if (m_drive_state != DriveState::ShellOpening)
m_secondary_status.motor_on = true; {
m_drive_state = DriveState::SpinningUp;
m_drive_event->Schedule(System::GetTicksPerSecond());
}
// reading TOC? interestingly this doesn't work for GetlocL though... // reading TOC? interestingly this doesn't work for GetlocL though...
CDImage::SubChannelQ subq; CDImage::SubChannelQ subq;
@ -698,8 +701,18 @@ TickCount CDROM::GetTicksForSeek(CDImage::LBA new_lba)
u32 ticks = std::max<u32>( 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));
// Motor spin-up time.
if (!m_secondary_status.motor_on) if (!m_secondary_status.motor_on)
ticks += tps; {
ticks += (m_drive_state == DriveState::SpinningUp) ? m_drive_event->GetTicksUntilNextExecution() : tps;
if (m_drive_state == DriveState::ShellOpening || m_drive_state == DriveState::SpinningUp)
{
m_drive_state = DriveState::Idle;
m_drive_event->Deactivate();
}
}
if (lba_diff >= 2550) if (lba_diff >= 2550)
ticks += static_cast<u32>((u64(tps) * 300) / 1000); ticks += static_cast<u32>((u64(tps) * 300) / 1000);
else else
@ -1471,6 +1484,10 @@ void CDROM::ExecuteDrive(TickCount ticks_late)
DoChangeSessionComplete(); DoChangeSessionComplete();
break; break;
case DriveState::SpinningUp:
DoSpinUpComplete();
break;
case DriveState::Idle: case DriveState::Idle:
default: default:
break; break;
@ -1691,7 +1708,10 @@ void CDROM::DoShellOpenComplete(TickCount ticks_late)
m_drive_event->Deactivate(); m_drive_event->Deactivate();
if (m_reader.HasMedia()) if (m_reader.HasMedia())
m_secondary_status.motor_on = true; {
m_drive_state = DriveState::SpinningUp;
m_drive_event->Schedule(System::GetTicksPerSecond());
}
} }
void CDROM::DoResetComplete(TickCount ticks_late) void CDROM::DoResetComplete(TickCount ticks_late)
@ -1870,6 +1890,15 @@ void CDROM::DoChangeSessionComplete()
} }
} }
void CDROM::DoSpinUpComplete()
{
Log_DebugPrintf("Spinup complete");
m_drive_state = DriveState::Idle;
m_drive_event->Deactivate();
m_secondary_status.ClearActiveBits();
m_secondary_status.motor_on = true;
}
void CDROM::DoIDRead() void CDROM::DoIDRead()
{ {
Log_DebugPrintf("ID read complete"); Log_DebugPrintf("ID read complete");
@ -2477,9 +2506,9 @@ void CDROM::DrawDebugWindow()
if (ImGui::CollapsingHeader("Status/Mode", ImGuiTreeNodeFlags_DefaultOpen)) if (ImGui::CollapsingHeader("Status/Mode", ImGuiTreeNodeFlags_DefaultOpen))
{ {
static constexpr std::array<const char*, 12> drive_state_names = { static constexpr std::array<const char*, 13> drive_state_names = {
{"Idle", "Opening Shell", "Resetting", "Seeking (Physical)", "Seeking (Logical)", "Reading ID", "Reading TOC", {"Idle", "Opening Shell", "Resetting", "Seeking (Physical)", "Seeking (Logical)", "Reading ID", "Reading TOC",
"Reading", "Playing", "Pausing", "Stopping", "Changing Session"}}; "Reading", "Playing", "Pausing", "Stopping", "Changing Session", "Spinning Up"}};
ImGui::Columns(3); ImGui::Columns(3);

View file

@ -146,7 +146,8 @@ private:
Playing, Playing,
Pausing, Pausing,
Stopping, Stopping,
ChangingSession ChangingSession,
SpinningUp
}; };
union StatusRegister union StatusRegister
@ -281,6 +282,7 @@ private:
void DoPauseComplete(); void DoPauseComplete();
void DoStopComplete(); void DoStopComplete();
void DoChangeSessionComplete(); void DoChangeSessionComplete();
void DoSpinUpComplete();
void DoIDRead(); void DoIDRead();
void DoTOCRead(); void DoTOCRead();
void DoSectorRead(); void DoSectorRead();