mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-30 09:35:40 +00:00
CDROM: Implement fast forward/rewind
This commit is contained in:
parent
29467d40c8
commit
a6947fbc70
|
@ -198,6 +198,10 @@ bool CDROM::DoState(StateWrapper& sw)
|
||||||
sw.Do(&m_last_cdda_report_frame_nibble);
|
sw.Do(&m_last_cdda_report_frame_nibble);
|
||||||
sw.Do(&m_play_track_number_bcd);
|
sw.Do(&m_play_track_number_bcd);
|
||||||
sw.Do(&m_async_command_parameter);
|
sw.Do(&m_async_command_parameter);
|
||||||
|
|
||||||
|
// TODO: Uncomment on the next save state version bump.
|
||||||
|
//sw.Do(&m_fast_forward_rate);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -228,6 +232,7 @@ bool CDROM::DoState(StateWrapper& sw)
|
||||||
m_reader.QueueReadSector(requested_sector);
|
m_reader.QueueReadSector(requested_sector);
|
||||||
UpdateCommandEvent();
|
UpdateCommandEvent();
|
||||||
m_drive_event->SetState(!IsDriveIdle());
|
m_drive_event->SetState(!IsDriveIdle());
|
||||||
|
m_fast_forward_rate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !sw.HasError();
|
return !sw.HasError();
|
||||||
|
@ -946,6 +951,7 @@ void CDROM::ExecuteCommand()
|
||||||
(m_drive_state == DriveState::Playing || (IsSeeking() && m_play_after_seek)))
|
(m_drive_state == DriveState::Playing || (IsSeeking() && m_play_after_seek)))
|
||||||
{
|
{
|
||||||
Log_DevPrintf("Ignoring play command with no/same setloc, already playing/playing after seek");
|
Log_DevPrintf("Ignoring play command with no/same setloc, already playing/playing after seek");
|
||||||
|
m_fast_forward_rate = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -960,6 +966,48 @@ void CDROM::ExecuteCommand()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::Forward:
|
||||||
|
{
|
||||||
|
if (m_drive_state != DriveState::Playing || !CanReadMedia())
|
||||||
|
{
|
||||||
|
SendErrorResponse(STAT_ERROR, ERROR_REASON_NOT_READY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendACKAndStat();
|
||||||
|
|
||||||
|
if (m_fast_forward_rate < 0)
|
||||||
|
m_fast_forward_rate = 0;
|
||||||
|
|
||||||
|
m_fast_forward_rate += static_cast<s8>(FAST_FORWARD_RATE_STEP);
|
||||||
|
m_fast_forward_rate = std::min<s8>(m_fast_forward_rate, static_cast<s8>(MAX_FAST_FORWARD_RATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
EndCommand();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Command::Backward:
|
||||||
|
{
|
||||||
|
if (m_drive_state != DriveState::Playing || !CanReadMedia())
|
||||||
|
{
|
||||||
|
SendErrorResponse(STAT_ERROR, ERROR_REASON_NOT_READY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendACKAndStat();
|
||||||
|
|
||||||
|
if (m_fast_forward_rate > 0)
|
||||||
|
m_fast_forward_rate = 0;
|
||||||
|
|
||||||
|
m_fast_forward_rate -= static_cast<s8>(FAST_FORWARD_RATE_STEP);
|
||||||
|
m_fast_forward_rate = std::max<s8>(m_fast_forward_rate, -static_cast<s8>(MAX_FAST_FORWARD_RATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
EndCommand();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case Command::Pause:
|
case Command::Pause:
|
||||||
{
|
{
|
||||||
if (m_secondary_status.seeking)
|
if (m_secondary_status.seeking)
|
||||||
|
@ -1392,6 +1440,7 @@ void CDROM::BeginPlaying(u8 track_bcd, TickCount ticks_late /* = 0 */, bool afte
|
||||||
Log_DebugPrintf("Starting playing CDDA track %x", track_bcd);
|
Log_DebugPrintf("Starting playing CDDA track %x", track_bcd);
|
||||||
m_last_cdda_report_frame_nibble = 0xFF;
|
m_last_cdda_report_frame_nibble = 0xFF;
|
||||||
m_play_track_number_bcd = track_bcd;
|
m_play_track_number_bcd = track_bcd;
|
||||||
|
m_fast_forward_rate = 0;
|
||||||
|
|
||||||
// if track zero, start from current position
|
// if track zero, start from current position
|
||||||
if (track_bcd != 0)
|
if (track_bcd != 0)
|
||||||
|
@ -1779,6 +1828,7 @@ void CDROM::DoSectorRead()
|
||||||
ProcessDataSectorHeader(m_reader.GetSectorBuffer().data());
|
ProcessDataSectorHeader(m_reader.GetSectorBuffer().data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 next_sector = m_current_lba + 1u;
|
||||||
if (is_data_sector && m_drive_state == DriveState::Reading)
|
if (is_data_sector && m_drive_state == DriveState::Reading)
|
||||||
{
|
{
|
||||||
ProcessDataSector(m_reader.GetSectorBuffer().data(), subq);
|
ProcessDataSector(m_reader.GetSectorBuffer().data(), subq);
|
||||||
|
@ -1787,6 +1837,9 @@ void CDROM::DoSectorRead()
|
||||||
(m_drive_state == DriveState::Playing || (m_drive_state == DriveState::Reading && m_mode.cdda)))
|
(m_drive_state == DriveState::Playing || (m_drive_state == DriveState::Reading && m_mode.cdda)))
|
||||||
{
|
{
|
||||||
ProcessCDDASector(m_reader.GetSectorBuffer().data(), subq);
|
ProcessCDDASector(m_reader.GetSectorBuffer().data(), subq);
|
||||||
|
|
||||||
|
if (m_fast_forward_rate != 0)
|
||||||
|
next_sector = m_current_lba + SignExtend32(m_fast_forward_rate);
|
||||||
}
|
}
|
||||||
else if (m_drive_state != DriveState::Reading && m_drive_state != DriveState::Playing)
|
else if (m_drive_state != DriveState::Reading && m_drive_state != DriveState::Playing)
|
||||||
{
|
{
|
||||||
|
@ -1798,7 +1851,7 @@ void CDROM::DoSectorRead()
|
||||||
is_data_sector ? "data" : "audio", is_data_sector ? "reading" : "playing");
|
is_data_sector ? "data" : "audio", is_data_sector ? "reading" : "playing");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_reader.QueueReadSector(m_current_lba + 1u);
|
m_reader.QueueReadSector(next_sector);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDROM::ProcessDataSectorHeader(const u8* raw_sector)
|
void CDROM::ProcessDataSectorHeader(const u8* raw_sector)
|
||||||
|
|
|
@ -69,6 +69,9 @@ private:
|
||||||
AUDIO_FIFO_LOW_WATERMARK = 5,
|
AUDIO_FIFO_LOW_WATERMARK = 5,
|
||||||
|
|
||||||
BASE_RESET_TICKS = 400000,
|
BASE_RESET_TICKS = 400000,
|
||||||
|
|
||||||
|
MAX_FAST_FORWARD_RATE = 12,
|
||||||
|
FAST_FORWARD_RATE_STEP = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr u8 INTERRUPT_REGISTER_MASK = 0x1F;
|
static constexpr u8 INTERRUPT_REGISTER_MASK = 0x1F;
|
||||||
|
@ -314,6 +317,7 @@ private:
|
||||||
u8 m_last_cdda_report_frame_nibble = 0xFF;
|
u8 m_last_cdda_report_frame_nibble = 0xFF;
|
||||||
u8 m_play_track_number_bcd = 0xFF;
|
u8 m_play_track_number_bcd = 0xFF;
|
||||||
u8 m_async_command_parameter = 0x00;
|
u8 m_async_command_parameter = 0x00;
|
||||||
|
s8 m_fast_forward_rate = 0;
|
||||||
|
|
||||||
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