CDROM: Properly handle audio sectors in SeekL
This commit is contained in:
parent
f12b97e98b
commit
d6209937fb
|
@ -549,7 +549,8 @@ void CDROM::Execute(TickCount ticks)
|
||||||
DoSpinUpComplete();
|
DoSpinUpComplete();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DriveState::Seeking:
|
case DriveState::SeekingPhysical:
|
||||||
|
case DriveState::SeekingLogical:
|
||||||
DoSeekComplete();
|
DoSeekComplete();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -717,8 +718,8 @@ void CDROM::ExecuteCommand()
|
||||||
case Command::SeekL:
|
case Command::SeekL:
|
||||||
case Command::SeekP:
|
case Command::SeekP:
|
||||||
{
|
{
|
||||||
// TODO: Data vs audio mode
|
const bool logical = (m_command == Command::SeekL);
|
||||||
Log_DebugPrintf("CDROM seek command");
|
Log_DebugPrintf("CDROM %s command", logical ? "SeekL" : "SeekP");
|
||||||
if (!m_media)
|
if (!m_media)
|
||||||
{
|
{
|
||||||
SendErrorResponse(0x80);
|
SendErrorResponse(0x80);
|
||||||
|
@ -726,7 +727,7 @@ void CDROM::ExecuteCommand()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SendACKAndStat();
|
SendACKAndStat();
|
||||||
BeginSeeking(false, false);
|
BeginSeeking(logical, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndCommand();
|
EndCommand();
|
||||||
|
@ -1022,7 +1023,7 @@ void CDROM::BeginReading()
|
||||||
Log_DebugPrintf("Starting reading");
|
Log_DebugPrintf("Starting reading");
|
||||||
if (m_setloc_pending)
|
if (m_setloc_pending)
|
||||||
{
|
{
|
||||||
BeginSeeking(true, false);
|
BeginSeeking(true, true, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1059,7 +1060,7 @@ void CDROM::BeginPlaying(u8 track_bcd)
|
||||||
|
|
||||||
if (m_setloc_pending)
|
if (m_setloc_pending)
|
||||||
{
|
{
|
||||||
BeginSeeking(false, true);
|
BeginSeeking(false, false, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1074,7 +1075,7 @@ void CDROM::BeginPlaying(u8 track_bcd)
|
||||||
m_system->SetDowncount(m_drive_remaining_ticks);
|
m_system->SetDowncount(m_drive_remaining_ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDROM::BeginSeeking(bool read_after_seek, bool play_after_seek)
|
void CDROM::BeginSeeking(bool logical, bool read_after_seek, bool play_after_seek)
|
||||||
{
|
{
|
||||||
if (!m_setloc_pending)
|
if (!m_setloc_pending)
|
||||||
Log_WarningPrintf("Seeking without setloc set");
|
Log_WarningPrintf("Seeking without setloc set");
|
||||||
|
@ -1084,7 +1085,8 @@ void CDROM::BeginSeeking(bool read_after_seek, bool play_after_seek)
|
||||||
m_play_after_seek = play_after_seek;
|
m_play_after_seek = play_after_seek;
|
||||||
m_setloc_pending = false;
|
m_setloc_pending = false;
|
||||||
|
|
||||||
Log_DebugPrintf("Seeking to [%02u:%02u:%02u]", m_seek_position.minute, m_seek_position.second, m_seek_position.frame);
|
Log_DebugPrintf("Seeking to [%02u:%02u:%02u] (%s)", m_seek_position.minute, m_seek_position.second,
|
||||||
|
m_seek_position.frame, logical ? "logical" : "physical");
|
||||||
|
|
||||||
const TickCount seek_time = GetTicksForSeek();
|
const TickCount seek_time = GetTicksForSeek();
|
||||||
|
|
||||||
|
@ -1092,7 +1094,7 @@ void CDROM::BeginSeeking(bool read_after_seek, bool play_after_seek)
|
||||||
m_secondary_status.motor_on = true;
|
m_secondary_status.motor_on = true;
|
||||||
m_sector_buffer.clear();
|
m_sector_buffer.clear();
|
||||||
|
|
||||||
m_drive_state = DriveState::Seeking;
|
m_drive_state = logical ? DriveState::SeekingLogical : DriveState::SeekingPhysical;
|
||||||
m_drive_remaining_ticks = seek_time;
|
m_drive_remaining_ticks = seek_time;
|
||||||
m_system->SetDowncount(m_drive_remaining_ticks);
|
m_system->SetDowncount(m_drive_remaining_ticks);
|
||||||
}
|
}
|
||||||
|
@ -1110,12 +1112,38 @@ void CDROM::DoSpinUpComplete()
|
||||||
|
|
||||||
void CDROM::DoSeekComplete()
|
void CDROM::DoSeekComplete()
|
||||||
{
|
{
|
||||||
|
const bool logical = (m_drive_state == DriveState::SeekingLogical);
|
||||||
m_drive_state = DriveState::Idle;
|
m_drive_state = DriveState::Idle;
|
||||||
m_secondary_status.ClearActiveBits();
|
m_secondary_status.ClearActiveBits();
|
||||||
m_sector_buffer.clear();
|
m_sector_buffer.clear();
|
||||||
|
|
||||||
// seek and update sub-q for ReadP command
|
// seek and update sub-q for ReadP command
|
||||||
if (m_media && m_media->Seek(m_seek_position) && m_media->ReadSubChannelQ(&m_last_subq))
|
// TODO: Check SubQ checksum
|
||||||
|
CDImage::SubChannelQ subq;
|
||||||
|
bool seek_okay = (m_media && m_media->Seek(m_seek_position) && m_media->ReadSubChannelQ(&subq));
|
||||||
|
if (seek_okay)
|
||||||
|
{
|
||||||
|
m_last_subq = subq;
|
||||||
|
|
||||||
|
// check for data header for logical seeks
|
||||||
|
if (logical)
|
||||||
|
{
|
||||||
|
u8 raw_sector[CDImage::RAW_SECTOR_SIZE];
|
||||||
|
seek_okay &= m_media->ReadRawSector(raw_sector);
|
||||||
|
seek_okay &= m_media->Seek(m_media->GetPositionOnDisc() - 1);
|
||||||
|
if (seek_okay)
|
||||||
|
{
|
||||||
|
ProcessDataSectorHeader(raw_sector);
|
||||||
|
|
||||||
|
// ensure the location matches up (it should)
|
||||||
|
const auto [seek_mm, seek_ss, seek_ff] = m_seek_position.ToBCD();
|
||||||
|
seek_okay = (m_last_sector_header.minute == seek_mm && m_last_sector_header.second == seek_ss &&
|
||||||
|
m_last_sector_header.frame == seek_ff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seek_okay)
|
||||||
{
|
{
|
||||||
// seek complete, transition to play/read if requested
|
// seek complete, transition to play/read if requested
|
||||||
// INT2 is not sent on play/read
|
// INT2 is not sent on play/read
|
||||||
|
@ -1135,8 +1163,8 @@ void CDROM::DoSeekComplete()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log_WarningPrintf("Seek to [%02u:%02u:%02u] failed", m_seek_position.minute, m_seek_position.second,
|
Log_WarningPrintf("%s seek to [%02u:%02u:%02u] failed", logical ? "Logical" : "Physical", m_seek_position.minute,
|
||||||
m_seek_position.frame);
|
m_seek_position.second, m_seek_position.frame);
|
||||||
m_secondary_status.seek_error = true;
|
m_secondary_status.seek_error = true;
|
||||||
SendAsyncErrorResponse(0x80);
|
SendAsyncErrorResponse(0x80);
|
||||||
}
|
}
|
||||||
|
@ -1201,6 +1229,7 @@ void CDROM::DoTOCRead()
|
||||||
void CDROM::DoSectorRead()
|
void CDROM::DoSectorRead()
|
||||||
{
|
{
|
||||||
// TODO: Error handling
|
// TODO: Error handling
|
||||||
|
// TODO: Check SubQ checksum.
|
||||||
CDImage::SubChannelQ subq;
|
CDImage::SubChannelQ subq;
|
||||||
if (!m_media->ReadSubChannelQ(&subq))
|
if (!m_media->ReadSubChannelQ(&subq))
|
||||||
Panic("SubChannel Q read failed");
|
Panic("SubChannel Q read failed");
|
||||||
|
@ -1235,6 +1264,8 @@ void CDROM::DoSectorRead()
|
||||||
if (!m_media->ReadRawSector(raw_sector))
|
if (!m_media->ReadRawSector(raw_sector))
|
||||||
Panic("Sector read failed");
|
Panic("Sector read failed");
|
||||||
|
|
||||||
|
m_last_subq = subq;
|
||||||
|
|
||||||
if (is_data_sector && m_drive_state == DriveState::Reading)
|
if (is_data_sector && m_drive_state == DriveState::Reading)
|
||||||
{
|
{
|
||||||
ProcessDataSector(raw_sector, subq);
|
ProcessDataSector(raw_sector, subq);
|
||||||
|
@ -1257,16 +1288,18 @@ void CDROM::DoSectorRead()
|
||||||
m_system->SetDowncount(m_drive_remaining_ticks);
|
m_system->SetDowncount(m_drive_remaining_ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDROM::ProcessDataSector(const u8* raw_sector, const CDImage::SubChannelQ& subq)
|
void CDROM::ProcessDataSectorHeader(const u8* raw_sector)
|
||||||
{
|
{
|
||||||
std::memcpy(&m_last_sector_header, &raw_sector[SECTOR_SYNC_SIZE], sizeof(m_last_sector_header));
|
std::memcpy(&m_last_sector_header, &raw_sector[SECTOR_SYNC_SIZE], sizeof(m_last_sector_header));
|
||||||
std::memcpy(&m_last_sector_subheader, &raw_sector[SECTOR_SYNC_SIZE + sizeof(m_last_sector_header)],
|
std::memcpy(&m_last_sector_subheader, &raw_sector[SECTOR_SYNC_SIZE + sizeof(m_last_sector_header)],
|
||||||
sizeof(m_last_sector_subheader));
|
sizeof(m_last_sector_subheader));
|
||||||
|
|
||||||
// TODO: Check SubQ checksum.
|
|
||||||
m_last_subq = subq;
|
|
||||||
|
|
||||||
m_secondary_status.header_valid = true;
|
m_secondary_status.header_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDROM::ProcessDataSector(const u8* raw_sector, const CDImage::SubChannelQ& subq)
|
||||||
|
{
|
||||||
|
ProcessDataSectorHeader(raw_sector);
|
||||||
|
|
||||||
Log_DevPrintf("Read sector %u: mode %u submode 0x%02X", m_media->GetPositionOnDisc() - 1,
|
Log_DevPrintf("Read sector %u: mode %u submode 0x%02X", m_media->GetPositionOnDisc() - 1,
|
||||||
ZeroExtend32(m_last_sector_header.sector_mode), ZeroExtend32(m_last_sector_subheader.submode.bits));
|
ZeroExtend32(m_last_sector_header.sector_mode), ZeroExtend32(m_last_sector_subheader.submode.bits));
|
||||||
|
@ -1493,8 +1526,6 @@ void CDROM::ProcessCDDASector(const u8* raw_sector, const CDImage::SubChannelQ&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_last_subq = subq;
|
|
||||||
|
|
||||||
// Apply volume when pushing sectors to SPU.
|
// Apply volume when pushing sectors to SPU.
|
||||||
if (m_muted)
|
if (m_muted)
|
||||||
return;
|
return;
|
||||||
|
@ -1571,8 +1602,9 @@ void CDROM::DrawDebugWindow()
|
||||||
|
|
||||||
if (ImGui::CollapsingHeader("Status/Mode", ImGuiTreeNodeFlags_DefaultOpen))
|
if (ImGui::CollapsingHeader("Status/Mode", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
{
|
{
|
||||||
static constexpr std::array<const char*, 9> drive_state_names = {
|
static constexpr std::array<const char*, 10> drive_state_names = {{"Idle", "Spinning Up", "Seeking (Physical)",
|
||||||
{"Idle", "Spinning Up", "Seeking", "Reading ID", "Reading TOC", "Reading", "Playing", "Pausing", "Stopping"}};
|
"Seeking (Logical)", "Reading ID", "Reading TOC",
|
||||||
|
"Reading", "Playing", "Pausing", "Stopping"}};
|
||||||
|
|
||||||
ImGui::Columns(3);
|
ImGui::Columns(3);
|
||||||
|
|
||||||
|
@ -1634,7 +1666,7 @@ void CDROM::DrawDebugWindow()
|
||||||
ImGui::TextColored(m_status.BUSYSTS ? active_color : inactive_color, "BUSYSTS: %s",
|
ImGui::TextColored(m_status.BUSYSTS ? active_color : inactive_color, "BUSYSTS: %s",
|
||||||
m_status.BUSYSTS ? "Yes" : "No");
|
m_status.BUSYSTS ? "Yes" : "No");
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
ImGui::TextColored(m_secondary_status.header_valid ? active_color : inactive_color, "Reading: %s",
|
ImGui::TextColored(m_secondary_status.header_valid ? active_color : inactive_color, "Header Valid: %s",
|
||||||
m_secondary_status.header_valid ? "Yes" : "No");
|
m_secondary_status.header_valid ? "Yes" : "No");
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
ImGui::TextColored(m_mode.read_raw_sector ? active_color : inactive_color, "Read Raw Sectors: %s",
|
ImGui::TextColored(m_mode.read_raw_sector ? active_color : inactive_color, "Read Raw Sectors: %s",
|
||||||
|
|
|
@ -110,7 +110,8 @@ private:
|
||||||
{
|
{
|
||||||
Idle,
|
Idle,
|
||||||
SpinningUp,
|
SpinningUp,
|
||||||
Seeking,
|
SeekingPhysical,
|
||||||
|
SeekingLogical,
|
||||||
ReadingID,
|
ReadingID,
|
||||||
ReadingTOC,
|
ReadingTOC,
|
||||||
Reading,
|
Reading,
|
||||||
|
@ -205,10 +206,11 @@ private:
|
||||||
void DoIDRead();
|
void DoIDRead();
|
||||||
void DoTOCRead();
|
void DoTOCRead();
|
||||||
void DoSectorRead();
|
void DoSectorRead();
|
||||||
|
void ProcessDataSectorHeader(const u8* raw_sector);
|
||||||
void ProcessDataSector(const u8* raw_sector, const CDImage::SubChannelQ& subq);
|
void ProcessDataSector(const u8* raw_sector, const CDImage::SubChannelQ& subq);
|
||||||
void ProcessXAADPCMSector(const u8* raw_sector, const CDImage::SubChannelQ& subq);
|
void ProcessXAADPCMSector(const u8* raw_sector, const CDImage::SubChannelQ& subq);
|
||||||
void ProcessCDDASector(const u8* raw_sector, const CDImage::SubChannelQ& subq);
|
void ProcessCDDASector(const u8* raw_sector, const CDImage::SubChannelQ& subq);
|
||||||
void BeginSeeking(bool read_after_seek, bool play_after_seek);
|
void BeginSeeking(bool logical, bool read_after_seek, bool play_after_seek);
|
||||||
void LoadDataFIFO();
|
void LoadDataFIFO();
|
||||||
|
|
||||||
System* m_system = nullptr;
|
System* m_system = nullptr;
|
||||||
|
|
Loading…
Reference in New Issue