CDROM: Adjust ACK timings to be closer to hardware test results

Fixes Shrek Treasure Hunt.
This commit is contained in:
Connor McLaughlin 2020-03-31 22:28:48 +10:00
parent 8439e1c54e
commit 00c24c2501
2 changed files with 29 additions and 11 deletions

View file

@ -226,7 +226,7 @@ u8 CDROM::ReadRegister(u32 offset)
switch (offset) switch (offset)
{ {
case 0: // status register case 0: // status register
Log_TracePrintf("CDROM read status register <- 0x%08X", m_status.bits); Log_TracePrintf("CDROM read status register -> 0x%08X", m_status.bits);
return m_status.bits; return m_status.bits;
case 1: // always response FIFO case 1: // always response FIFO
@ -239,7 +239,7 @@ u8 CDROM::ReadRegister(u32 offset)
const u8 value = m_response_fifo.Pop(); const u8 value = m_response_fifo.Pop();
UpdateStatusRegister(); UpdateStatusRegister();
Log_DebugPrintf("CDROM read response FIFO <- 0x%08X", ZeroExtend32(value)); Log_DebugPrintf("CDROM read response FIFO -> 0x%08X", ZeroExtend32(value));
return value; return value;
} }
@ -247,7 +247,7 @@ u8 CDROM::ReadRegister(u32 offset)
{ {
const u8 value = m_data_fifo.Pop(); const u8 value = m_data_fifo.Pop();
UpdateStatusRegister(); UpdateStatusRegister();
Log_DebugPrintf("CDROM read data FIFO <- 0x%08X", ZeroExtend32(value)); Log_DebugPrintf("CDROM read data FIFO -> 0x%08X", ZeroExtend32(value));
return value; return value;
} }
@ -256,13 +256,13 @@ u8 CDROM::ReadRegister(u32 offset)
if (m_status.index & 1) if (m_status.index & 1)
{ {
const u8 value = m_interrupt_flag_register | ~INTERRUPT_REGISTER_MASK; const u8 value = m_interrupt_flag_register | ~INTERRUPT_REGISTER_MASK;
Log_DebugPrintf("CDROM read interrupt flag register <- 0x%02X", ZeroExtend32(value)); Log_DebugPrintf("CDROM read interrupt flag register -> 0x%02X", ZeroExtend32(value));
return value; return value;
} }
else else
{ {
const u8 value = m_interrupt_enable_register | ~INTERRUPT_REGISTER_MASK; const u8 value = m_interrupt_enable_register | ~INTERRUPT_REGISTER_MASK;
Log_DebugPrintf("CDROM read interrupt enable register <- 0x%02X", ZeroExtend32(value)); Log_DebugPrintf("CDROM read interrupt enable register -> 0x%02X", ZeroExtend32(value));
return value; return value;
} }
} }
@ -293,7 +293,7 @@ void CDROM::WriteRegister(u32 offset, u8 value)
if (HasPendingCommand()) if (HasPendingCommand())
{ {
Log_WarningPrintf("Cancelling pending command 0x%02X", static_cast<u8>(m_command)); Log_WarningPrintf("Cancelling pending command 0x%02X", static_cast<u8>(m_command));
m_command = Command::None; AbortCommand();
} }
BeginCommand(static_cast<Command>(value)); BeginCommand(static_cast<Command>(value));
@ -516,10 +516,19 @@ void CDROM::UpdateInterruptRequest()
m_interrupt_controller->InterruptRequest(InterruptController::IRQ::CDROM); m_interrupt_controller->InterruptRequest(InterruptController::IRQ::CDROM);
} }
TickCount CDROM::GetAckDelayForCommand() const TickCount CDROM::GetAckDelayForCommand(Command command) const
{ {
const u32 default_ack_delay = 10000; if (command == Command::Init)
return default_ack_delay; {
// Init takes longer.
return 120000;
}
// Tests show that the average time to acknowledge a command is significantly higher when a disc is in the drive,
// presumably because the controller is busy doing discy-things.
constexpr u32 default_ack_delay_no_disc = 20000;
constexpr u32 default_ack_delay_with_disc = 30000;
return HasMedia() ? default_ack_delay_with_disc : default_ack_delay_no_disc;
} }
TickCount CDROM::GetTicksForRead() const TickCount CDROM::GetTicksForRead() const
@ -551,7 +560,7 @@ TickCount CDROM::GetTicksForSeek() const
void CDROM::BeginCommand(Command command) void CDROM::BeginCommand(Command command)
{ {
m_command = command; m_command = command;
m_command_event->Schedule(GetAckDelayForCommand()); m_command_event->Schedule(GetAckDelayForCommand(command));
UpdateCommandEvent(); UpdateCommandEvent();
UpdateStatusRegister(); UpdateStatusRegister();
} }
@ -565,6 +574,13 @@ void CDROM::EndCommand()
UpdateStatusRegister(); UpdateStatusRegister();
} }
void CDROM::AbortCommand()
{
m_command = Command::None;
m_command_event->Deactivate();
UpdateStatusRegister();
}
void CDROM::ExecuteCommand() void CDROM::ExecuteCommand()
{ {
Log_DevPrintf("CDROM executing command 0x%02X", ZeroExtend32(static_cast<u8>(m_command))); Log_DevPrintf("CDROM executing command 0x%02X", ZeroExtend32(static_cast<u8>(m_command)));
@ -751,6 +767,7 @@ void CDROM::ExecuteCommand()
case Command::Pause: case Command::Pause:
{ {
// TODO: Should return an error if seeking.
const bool was_reading = (m_drive_state == DriveState::Reading || m_drive_state == DriveState::Playing); const bool was_reading = (m_drive_state == DriveState::Reading || m_drive_state == DriveState::Playing);
const TickCount pause_time = was_reading ? (m_mode.double_speed ? 2000000 : 1000000) : 7000; const TickCount pause_time = was_reading ? (m_mode.double_speed ? 2000000 : 1000000) : 7000;
Log_DebugPrintf("CDROM pause command"); Log_DebugPrintf("CDROM pause command");

View file

@ -201,11 +201,12 @@ private:
void UpdateStatusRegister(); void UpdateStatusRegister();
void UpdateInterruptRequest(); void UpdateInterruptRequest();
TickCount GetAckDelayForCommand() const; TickCount GetAckDelayForCommand(Command command) const;
TickCount GetTicksForRead() const; TickCount GetTicksForRead() const;
TickCount GetTicksForSeek() const; TickCount GetTicksForSeek() const;
void BeginCommand(Command command); // also update status register void BeginCommand(Command command); // also update status register
void EndCommand(); // also updates status register void EndCommand(); // also updates status register
void AbortCommand();
void ExecuteCommand(); void ExecuteCommand();
void ExecuteTestCommand(u8 subcommand); void ExecuteTestCommand(u8 subcommand);
void UpdateCommandEvent(); void UpdateCommandEvent();