mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 06:15:38 +00:00
CDROM: Fix track skip behavior with track=0
Fixes Doom.
This commit is contained in:
parent
525bbf48d7
commit
8cfb8d7922
|
@ -106,7 +106,7 @@ bool CDROM::DoState(StateWrapper& sw)
|
||||||
sw.DoBytes(&m_last_sector_subheader, sizeof(m_last_sector_subheader));
|
sw.DoBytes(&m_last_sector_subheader, sizeof(m_last_sector_subheader));
|
||||||
sw.DoBytes(&m_last_subq, sizeof(m_last_subq));
|
sw.DoBytes(&m_last_subq, sizeof(m_last_subq));
|
||||||
sw.Do(&m_last_cdda_report_frame_nibble);
|
sw.Do(&m_last_cdda_report_frame_nibble);
|
||||||
sw.Do(&m_auto_pause_track_number);
|
sw.Do(&m_play_track_number_bcd);
|
||||||
sw.Do(&m_cd_audio_volume_matrix);
|
sw.Do(&m_cd_audio_volume_matrix);
|
||||||
sw.Do(&m_next_cd_audio_volume_matrix);
|
sw.Do(&m_next_cd_audio_volume_matrix);
|
||||||
sw.Do(&m_xa_last_samples);
|
sw.Do(&m_xa_last_samples);
|
||||||
|
@ -449,6 +449,7 @@ void CDROM::DeliverAsyncInterrupt()
|
||||||
m_interrupt_flag_register = m_pending_async_interrupt;
|
m_interrupt_flag_register = m_pending_async_interrupt;
|
||||||
m_pending_async_interrupt = 0;
|
m_pending_async_interrupt = 0;
|
||||||
UpdateInterruptRequest();
|
UpdateInterruptRequest();
|
||||||
|
UpdateStatusRegister();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDROM::SendACKAndStat()
|
void CDROM::SendACKAndStat()
|
||||||
|
@ -743,7 +744,7 @@ void CDROM::ExecuteCommand()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SendACKAndStat();
|
SendACKAndStat();
|
||||||
BeginReading(false);
|
BeginReading();
|
||||||
}
|
}
|
||||||
|
|
||||||
EndCommand();
|
EndCommand();
|
||||||
|
@ -761,22 +762,8 @@ void CDROM::ExecuteCommand()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if track zero, start from current position
|
|
||||||
if (track != 0)
|
|
||||||
{
|
|
||||||
// play specific track?
|
|
||||||
if (track > m_media->GetTrackCount())
|
|
||||||
{
|
|
||||||
// restart current track
|
|
||||||
track = Truncate8(m_media->GetTrackNumber());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_setloc_position = m_media->GetTrackStartMSFPosition(track);
|
|
||||||
m_setloc_pending = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendACKAndStat();
|
SendACKAndStat();
|
||||||
BeginReading(true);
|
BeginPlaying(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndCommand();
|
EndCommand();
|
||||||
|
@ -1024,32 +1011,65 @@ void CDROM::ExecuteTestCommand(u8 subcommand)
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
Log_ErrorPrintf("Unknown test command 0x%02X", subcommand);
|
Log_ErrorPrintf("Unknown test command 0x%02X", subcommand);
|
||||||
|
Panic("Unknown test command");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDROM::BeginReading(bool cdda)
|
void CDROM::BeginReading()
|
||||||
{
|
{
|
||||||
Log_DebugPrintf("Starting %s", cdda ? "playing CDDA" : "reading");
|
Log_DebugPrintf("Starting reading");
|
||||||
|
|
||||||
if (m_setloc_pending)
|
if (m_setloc_pending)
|
||||||
{
|
{
|
||||||
BeginSeeking(!cdda, cdda);
|
BeginSeeking(true, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_secondary_status.ClearActiveBits();
|
m_secondary_status.ClearActiveBits();
|
||||||
m_secondary_status.motor_on = true;
|
m_secondary_status.motor_on = true;
|
||||||
m_secondary_status.playing_cdda = cdda;
|
|
||||||
|
|
||||||
// TODO: Should the sector buffer be cleared here?
|
// TODO: Should the sector buffer be cleared here?
|
||||||
m_sector_buffer.clear();
|
m_sector_buffer.clear();
|
||||||
|
|
||||||
m_last_cdda_report_frame_nibble = 0xFF;
|
m_drive_state = DriveState::Reading;
|
||||||
m_auto_pause_track_number = Truncate8(m_media->GetTrackNumber());
|
m_drive_remaining_ticks = GetTicksForRead();
|
||||||
|
m_system->SetDowncount(m_drive_remaining_ticks);
|
||||||
|
}
|
||||||
|
|
||||||
m_drive_state = cdda ? DriveState::Playing : DriveState::Reading;
|
void CDROM::BeginPlaying(u8 track_bcd)
|
||||||
|
{
|
||||||
|
Log_DebugPrintf("Starting playing CDDA track %x", track_bcd);
|
||||||
|
m_last_cdda_report_frame_nibble = 0xFF;
|
||||||
|
m_play_track_number_bcd = track_bcd;
|
||||||
|
|
||||||
|
// if track zero, start from current position
|
||||||
|
if (track_bcd != 0)
|
||||||
|
{
|
||||||
|
// play specific track?
|
||||||
|
if (track_bcd > m_media->GetTrackCount())
|
||||||
|
{
|
||||||
|
// restart current track
|
||||||
|
track_bcd = DecimalToBCD(Truncate8(m_media->GetTrackNumber()));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_setloc_position = m_media->GetTrackStartMSFPosition(BCDToDecimal(track_bcd));
|
||||||
|
m_setloc_pending = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_setloc_pending)
|
||||||
|
{
|
||||||
|
BeginSeeking(false, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_secondary_status.ClearActiveBits();
|
||||||
|
m_secondary_status.motor_on = true;
|
||||||
|
|
||||||
|
// TODO: Should the sector buffer be cleared here?
|
||||||
|
m_sector_buffer.clear();
|
||||||
|
|
||||||
|
m_drive_state = DriveState::Playing;
|
||||||
m_drive_remaining_ticks = GetTicksForRead();
|
m_drive_remaining_ticks = GetTicksForRead();
|
||||||
m_system->SetDowncount(m_drive_remaining_ticks);
|
m_system->SetDowncount(m_drive_remaining_ticks);
|
||||||
}
|
}
|
||||||
|
@ -1098,10 +1118,14 @@ void CDROM::DoSeekComplete()
|
||||||
if (m_media && m_media->Seek(m_seek_position) && m_media->ReadSubChannelQ(&m_last_subq))
|
if (m_media && m_media->Seek(m_seek_position) && m_media->ReadSubChannelQ(&m_last_subq))
|
||||||
{
|
{
|
||||||
// seek complete, transition to play/read if requested
|
// seek complete, transition to play/read if requested
|
||||||
if (m_play_after_seek || m_read_after_seek)
|
// INT2 is not sent on play/read
|
||||||
|
if (m_read_after_seek)
|
||||||
{
|
{
|
||||||
// INT2 is not sent on play/read
|
BeginReading();
|
||||||
BeginReading(m_play_after_seek);
|
}
|
||||||
|
else if (m_play_after_seek)
|
||||||
|
{
|
||||||
|
BeginPlaying(m_play_track_number_bcd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1181,31 +1205,53 @@ void CDROM::DoSectorRead()
|
||||||
if (!m_media->ReadSubChannelQ(&subq))
|
if (!m_media->ReadSubChannelQ(&subq))
|
||||||
Panic("SubChannel Q read failed");
|
Panic("SubChannel Q read failed");
|
||||||
|
|
||||||
if (m_mode.auto_pause && BCDToDecimal(subq.track_number_bcd) != m_auto_pause_track_number)
|
const bool is_data_sector = subq.control.data;
|
||||||
|
m_secondary_status.playing_cdda = !is_data_sector;
|
||||||
|
if (!is_data_sector)
|
||||||
{
|
{
|
||||||
// we don't want to update the position if the track changes, so we check it before reading the actual sector.
|
if (m_play_track_number_bcd == 0)
|
||||||
Log_DevPrintf("Auto pause at the end of track %u (LBA %u)", m_auto_pause_track_number,
|
{
|
||||||
m_media->GetPositionOnDisc());
|
// track number was not specified, but we've found the track now
|
||||||
|
Log_DebugPrintf("Setting playing track number to %u", m_play_track_number_bcd);
|
||||||
|
m_play_track_number_bcd = subq.track_number_bcd;
|
||||||
|
}
|
||||||
|
else if (m_mode.auto_pause && subq.track_number_bcd != m_play_track_number_bcd)
|
||||||
|
{
|
||||||
|
// we don't want to update the position if the track changes, so we check it before reading the actual sector.
|
||||||
|
Log_DevPrintf("Auto pause at the end of track %u (LBA %u)", m_play_track_number_bcd,
|
||||||
|
m_media->GetPositionOnDisc());
|
||||||
|
|
||||||
ClearAsyncInterrupt();
|
ClearAsyncInterrupt();
|
||||||
m_async_response_fifo.Push(m_secondary_status.bits);
|
m_async_response_fifo.Push(m_secondary_status.bits);
|
||||||
SetAsyncInterrupt(Interrupt::INT4);
|
SetAsyncInterrupt(Interrupt::INT4);
|
||||||
|
|
||||||
m_secondary_status.ClearActiveBits();
|
m_secondary_status.ClearActiveBits();
|
||||||
m_drive_state = DriveState::Idle;
|
m_drive_state = DriveState::Idle;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 raw_sector[CDImage::RAW_SECTOR_SIZE];
|
u8 raw_sector[CDImage::RAW_SECTOR_SIZE];
|
||||||
if (!m_media->ReadRawSector(raw_sector))
|
if (!m_media->ReadRawSector(raw_sector))
|
||||||
Panic("Sector read failed");
|
Panic("Sector read failed");
|
||||||
|
|
||||||
if (m_drive_state == DriveState::Reading)
|
if (is_data_sector && m_drive_state == DriveState::Reading)
|
||||||
|
{
|
||||||
ProcessDataSector(raw_sector, subq);
|
ProcessDataSector(raw_sector, subq);
|
||||||
else if (m_drive_state == DriveState::Playing)
|
}
|
||||||
|
else if (!is_data_sector && m_drive_state == DriveState::Playing)
|
||||||
|
{
|
||||||
ProcessCDDASector(raw_sector, subq);
|
ProcessCDDASector(raw_sector, subq);
|
||||||
else
|
}
|
||||||
|
else if (m_drive_state != DriveState::Reading && m_drive_state != DriveState::Playing)
|
||||||
|
{
|
||||||
Panic("Not reading or playing");
|
Panic("Not reading or playing");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log_WarningPrintf("Skipping sector %u as it is a %s sector and we're not %s", m_media->GetPositionOnDisc() - 1,
|
||||||
|
is_data_sector ? "data" : "audio", is_data_sector ? "reading" : "playing");
|
||||||
|
}
|
||||||
|
|
||||||
m_drive_remaining_ticks += GetTicksForRead();
|
m_drive_remaining_ticks += GetTicksForRead();
|
||||||
m_system->SetDowncount(m_drive_remaining_ticks);
|
m_system->SetDowncount(m_drive_remaining_ticks);
|
||||||
|
@ -1279,7 +1325,6 @@ void CDROM::ProcessDataSector(const u8* raw_sector, const CDImage::SubChannelQ&
|
||||||
|
|
||||||
m_async_response_fifo.Push(m_secondary_status.bits);
|
m_async_response_fifo.Push(m_secondary_status.bits);
|
||||||
SetAsyncInterrupt(Interrupt::INT1);
|
SetAsyncInterrupt(Interrupt::INT1);
|
||||||
UpdateStatusRegister();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::array<std::array<s16, 29>, 7> s_zigzag_table = {
|
static std::array<std::array<s16, 29>, 7> s_zigzag_table = {
|
||||||
|
@ -1416,7 +1461,7 @@ void CDROM::ProcessCDDASector(const u8* raw_sector, const CDImage::SubChannelQ&
|
||||||
|
|
||||||
if (m_mode.report_audio)
|
if (m_mode.report_audio)
|
||||||
{
|
{
|
||||||
const u8 frame_nibble = m_last_subq.absolute_frame_bcd >> 4;
|
const u8 frame_nibble = subq.absolute_frame_bcd >> 4;
|
||||||
if (m_last_cdda_report_frame_nibble != frame_nibble)
|
if (m_last_cdda_report_frame_nibble != frame_nibble)
|
||||||
{
|
{
|
||||||
m_last_cdda_report_frame_nibble = frame_nibble;
|
m_last_cdda_report_frame_nibble = frame_nibble;
|
||||||
|
@ -1429,7 +1474,7 @@ void CDROM::ProcessCDDASector(const u8* raw_sector, const CDImage::SubChannelQ&
|
||||||
m_async_response_fifo.Push(m_secondary_status.bits);
|
m_async_response_fifo.Push(m_secondary_status.bits);
|
||||||
m_async_response_fifo.Push(subq.track_number_bcd);
|
m_async_response_fifo.Push(subq.track_number_bcd);
|
||||||
m_async_response_fifo.Push(subq.index_number_bcd);
|
m_async_response_fifo.Push(subq.index_number_bcd);
|
||||||
if (m_last_subq.absolute_frame_bcd & 0x10)
|
if (subq.absolute_frame_bcd & 0x10)
|
||||||
{
|
{
|
||||||
m_async_response_fifo.Push(subq.relative_minute_bcd);
|
m_async_response_fifo.Push(subq.relative_minute_bcd);
|
||||||
m_async_response_fifo.Push(0x80 | subq.relative_second_bcd);
|
m_async_response_fifo.Push(0x80 | subq.relative_second_bcd);
|
||||||
|
|
|
@ -196,7 +196,8 @@ private:
|
||||||
void EndCommand(); // also updates status register
|
void EndCommand(); // also updates status register
|
||||||
void ExecuteCommand();
|
void ExecuteCommand();
|
||||||
void ExecuteTestCommand(u8 subcommand);
|
void ExecuteTestCommand(u8 subcommand);
|
||||||
void BeginReading(bool cdda);
|
void BeginReading();
|
||||||
|
void BeginPlaying(u8 track_bcd);
|
||||||
void DoSpinUpComplete();
|
void DoSpinUpComplete();
|
||||||
void DoSeekComplete();
|
void DoSeekComplete();
|
||||||
void DoPauseComplete();
|
void DoPauseComplete();
|
||||||
|
@ -245,7 +246,7 @@ private:
|
||||||
CDXA::XASubHeader m_last_sector_subheader{};
|
CDXA::XASubHeader m_last_sector_subheader{};
|
||||||
CDImage::SubChannelQ m_last_subq{};
|
CDImage::SubChannelQ m_last_subq{};
|
||||||
u8 m_last_cdda_report_frame_nibble = 0xFF;
|
u8 m_last_cdda_report_frame_nibble = 0xFF;
|
||||||
u8 m_auto_pause_track_number = 0xFF;
|
u8 m_play_track_number_bcd = 0xFF;
|
||||||
|
|
||||||
std::array<std::array<u8, 2>, 2> m_cd_audio_volume_matrix{};
|
std::array<std::array<u8, 2>, 2> m_cd_audio_volume_matrix{};
|
||||||
std::array<std::array<u8, 2>, 2> m_next_cd_audio_volume_matrix{};
|
std::array<std::array<u8, 2>, 2> m_next_cd_audio_volume_matrix{};
|
||||||
|
|
Loading…
Reference in a new issue