mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 23:55:40 +00:00
CDROM: Implement a heuristic for command cancelling
See note in source. Fixes loading times and slowed down audio in Voice Idol Collection - Pool Bar Story.
This commit is contained in:
parent
a4f79de7f6
commit
0672cf4873
|
@ -563,13 +563,7 @@ void CDROM::WriteRegister(u32 offset, u8 value)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
Log_DebugPrintf("CDROM command register <- 0x%02X", value);
|
Log_WarningPrintf("CDROM command register <- 0x%02X (%s)", value, s_command_info[value].name);
|
||||||
if (HasPendingCommand())
|
|
||||||
{
|
|
||||||
Log_WarningPrintf("Cancelling pending command 0x%02X", static_cast<u8>(m_command));
|
|
||||||
AbortCommand();
|
|
||||||
}
|
|
||||||
|
|
||||||
BeginCommand(static_cast<Command>(value));
|
BeginCommand(static_cast<Command>(value));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -857,8 +851,40 @@ TickCount CDROM::GetTicksForStop(bool motor_was_on)
|
||||||
|
|
||||||
void CDROM::BeginCommand(Command command)
|
void CDROM::BeginCommand(Command command)
|
||||||
{
|
{
|
||||||
|
TickCount ack_delay = GetAckDelayForCommand(command);
|
||||||
|
|
||||||
|
if (HasPendingCommand())
|
||||||
|
{
|
||||||
|
// The behavior here is kinda.. interesting. Some commands seem to take precedence over others, for example
|
||||||
|
// sending a Nop command followed by a GetlocP will return the GetlocP response, and the same for the inverse.
|
||||||
|
// However, other combinations result in strange behavior, for example sending a Setloc followed by a ReadN will
|
||||||
|
// fail with ERROR_REASON_INCORRECT_NUMBER_OF_PARAMETERS. This particular example happens in Voice Idol
|
||||||
|
// Collection - Pool Bar Story, and the loading time is lengthened as well as audio slowing down if this
|
||||||
|
// behavior is not correct. So, let's use a heuristic; if the number of parameters of the "old" command is
|
||||||
|
// greater than the "new" command, empty the FIFO, which will return the error when the command executes.
|
||||||
|
// Otherwise, override the command with the new one.
|
||||||
|
if (s_command_info[static_cast<u8>(m_command)].expected_parameters >
|
||||||
|
s_command_info[static_cast<u8>(command)].expected_parameters)
|
||||||
|
{
|
||||||
|
Log_WarningPrintf("Ignoring command 0x%02X (%s) and emptying FIFO as 0x%02x (%s) is still pending",
|
||||||
|
static_cast<u8>(command), s_command_info[static_cast<u8>(command)].name,
|
||||||
|
static_cast<u8>(m_command), s_command_info[static_cast<u8>(m_command)].name);
|
||||||
|
m_param_fifo.Clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log_WarningPrintf("Cancelling pending command 0x%02X (%s) for new command 0x%02X (%s)", static_cast<u8>(m_command),
|
||||||
|
s_command_info[static_cast<u8>(m_command)].name, static_cast<u8>(command),
|
||||||
|
s_command_info[static_cast<u8>(command)].name);
|
||||||
|
|
||||||
|
// subtract the currently-elapsed ack ticks from the new command
|
||||||
|
const TickCount elapsed_ticks = m_command_event->GetInterval() - m_command_event->GetTicksUntilNextExecution();
|
||||||
|
ack_delay = std::max(ack_delay - elapsed_ticks, 1);
|
||||||
|
m_command_event->Deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
m_command = command;
|
m_command = command;
|
||||||
m_command_event->Schedule(GetAckDelayForCommand(command));
|
m_command_event->SetIntervalAndSchedule(ack_delay);
|
||||||
UpdateCommandEvent();
|
UpdateCommandEvent();
|
||||||
UpdateStatusRegister();
|
UpdateStatusRegister();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue