mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-25 23:25:41 +00:00
CDImageDevice: Fix reading of pure audio CDs
This commit is contained in:
parent
83ebad1129
commit
3e8dd2c374
|
@ -232,7 +232,6 @@ private:
|
||||||
bool m_has_valid_subcode = false;
|
bool m_has_valid_subcode = false;
|
||||||
|
|
||||||
std::array<u8, CD_RAW_SECTOR_WITH_SUBCODE_SIZE> m_buffer;
|
std::array<u8, CD_RAW_SECTOR_WITH_SUBCODE_SIZE> m_buffer;
|
||||||
std::array<u8, SUBCHANNEL_BYTES_PER_FRAME> m_subq;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -339,7 +338,7 @@ bool CDImageDeviceWin32::Open(const char* filename, Error* error)
|
||||||
const TrackMode track_mode = control.data ? CDImage::TrackMode::Mode2Raw : CDImage::TrackMode::Audio;
|
const TrackMode track_mode = control.data ? CDImage::TrackMode::Mode2Raw : CDImage::TrackMode::Audio;
|
||||||
|
|
||||||
// TODO: How the hell do we handle pregaps here?
|
// TODO: How the hell do we handle pregaps here?
|
||||||
const u32 pregap_frames = (control.data && track_index == 0) ? 150 : 0;
|
const u32 pregap_frames = (track_index == 0) ? (FRAMES_PER_SECOND * 2) : 0;
|
||||||
if (pregap_frames > 0)
|
if (pregap_frames > 0)
|
||||||
{
|
{
|
||||||
Index pregap_index = {};
|
Index pregap_index = {};
|
||||||
|
@ -424,9 +423,22 @@ bool CDImageDeviceWin32::ReadSubChannelQ(SubChannelQ* subq, const Index& index,
|
||||||
if (m_current_lba != offset && !ReadSectorToBuffer(offset))
|
if (m_current_lba != offset && !ReadSectorToBuffer(offset))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// P, Q, ...
|
if (m_scsi_read_mode == SCSIReadMode::SubQOnly)
|
||||||
std::memcpy(subq->data.data(), m_subq.data(), SUBCHANNEL_BYTES_PER_FRAME);
|
{
|
||||||
return true;
|
// copy out subq
|
||||||
|
std::memcpy(subq->data.data(), m_buffer.data() + RAW_SECTOR_SIZE, SUBCHANNEL_BYTES_PER_FRAME);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else // if (m_scsi_read_mode == SCSIReadMode::Full || m_scsi_read_mode == SCSIReadMode::None)
|
||||||
|
{
|
||||||
|
// need to deinterleave the subcode
|
||||||
|
u8 deinterleaved_subcode[ALL_SUBCODE_SIZE];
|
||||||
|
DeinterleaveSubcode(m_buffer.data() + RAW_SECTOR_SIZE, deinterleaved_subcode);
|
||||||
|
|
||||||
|
// P, Q, ...
|
||||||
|
std::memcpy(subq->data.data(), deinterleaved_subcode + SUBCHANNEL_BYTES_PER_FRAME, SUBCHANNEL_BYTES_PER_FRAME);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDImageDeviceWin32::HasNonStandardSubchannel() const
|
bool CDImageDeviceWin32::HasNonStandardSubchannel() const
|
||||||
|
@ -535,19 +547,6 @@ bool CDImageDeviceWin32::ReadSectorToBuffer(LBA lba)
|
||||||
Log_ErrorFmt("Read of LBA {} failed: only got {} of {} bytes", lba, size.value(), expected_size);
|
Log_ErrorFmt("Read of LBA {} failed: only got {} of {} bytes", lba, size.value(), expected_size);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_scsi_read_mode == SCSIReadMode::Full)
|
|
||||||
{
|
|
||||||
// need to deinterleave the subcode
|
|
||||||
u8 deinterleaved_subcode[ALL_SUBCODE_SIZE];
|
|
||||||
DeinterleaveSubcode(m_buffer.data() + RAW_SECTOR_SIZE, deinterleaved_subcode);
|
|
||||||
std::memcpy(&m_subq, deinterleaved_subcode + SUBCHANNEL_BYTES_PER_FRAME, sizeof(m_subq)); // P,Q
|
|
||||||
}
|
|
||||||
else if (m_scsi_read_mode == SCSIReadMode::SubQOnly)
|
|
||||||
{
|
|
||||||
// copy out subq
|
|
||||||
std::memcpy(&m_subq, m_buffer.data() + RAW_SECTOR_SIZE, sizeof(m_subq));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -562,12 +561,58 @@ bool CDImageDeviceWin32::ReadSectorToBuffer(LBA lba)
|
||||||
bool CDImageDeviceWin32::DetermineReadMode(bool try_sptd)
|
bool CDImageDeviceWin32::DetermineReadMode(bool try_sptd)
|
||||||
{
|
{
|
||||||
// Prefer raw reads if we can use them
|
// Prefer raw reads if we can use them
|
||||||
const LBA track_1_lba = static_cast<LBA>(m_indices[m_tracks[0].first_index].file_offset);
|
const Index& first_index = m_indices[m_tracks[0].first_index];
|
||||||
const LBA track_1_subq_lba = track_1_lba + FRAMES_PER_SECOND * 2;
|
const LBA track_1_lba = static_cast<LBA>(first_index.file_offset);
|
||||||
|
const LBA track_1_subq_lba = first_index.start_lba_on_disc;
|
||||||
const bool check_subcode = ShouldTryReadingSubcode();
|
const bool check_subcode = ShouldTryReadingSubcode();
|
||||||
|
|
||||||
Log_DevPrint("Trying raw reads...");
|
if (try_sptd)
|
||||||
if (check_subcode && DoRawRead(track_1_lba))
|
{
|
||||||
|
std::optional<u32> transfer_size;
|
||||||
|
|
||||||
|
Log_DevPrint("Trying SCSI read with full subcode...");
|
||||||
|
if (check_subcode && (transfer_size = DoSCSIRead(track_1_lba, SCSIReadMode::Full)).has_value())
|
||||||
|
{
|
||||||
|
if (VerifySCSIReadData(std::span<u8>(m_buffer.data(), transfer_size.value()), SCSIReadMode::Full,
|
||||||
|
track_1_subq_lba))
|
||||||
|
{
|
||||||
|
Log_VerbosePrint("Using SCSI reads with subcode");
|
||||||
|
m_scsi_read_mode = SCSIReadMode::Full;
|
||||||
|
m_has_valid_subcode = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log_WarningPrint("Full subcode failed, trying SCSI read with only subq...");
|
||||||
|
if (check_subcode && (transfer_size = DoSCSIRead(track_1_lba, SCSIReadMode::SubQOnly)).has_value())
|
||||||
|
{
|
||||||
|
if (VerifySCSIReadData(std::span<u8>(m_buffer.data(), transfer_size.value()), SCSIReadMode::SubQOnly,
|
||||||
|
track_1_subq_lba))
|
||||||
|
{
|
||||||
|
Log_VerbosePrint("Using SCSI reads with subq only");
|
||||||
|
m_scsi_read_mode = SCSIReadMode::SubQOnly;
|
||||||
|
m_has_valid_subcode = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// As a last ditch effort, try SCSI without subcode.
|
||||||
|
Log_WarningPrint("Subq only failed failed, trying SCSI without subcode...");
|
||||||
|
if ((transfer_size = DoSCSIRead(track_1_lba, SCSIReadMode::Raw)).has_value())
|
||||||
|
{
|
||||||
|
if (VerifySCSIReadData(std::span<u8>(m_buffer.data(), transfer_size.value()), SCSIReadMode::Raw,
|
||||||
|
track_1_subq_lba))
|
||||||
|
{
|
||||||
|
Log_WarningPrint("Using SCSI raw reads, libcrypt games will not run correctly");
|
||||||
|
m_scsi_read_mode = SCSIReadMode::Raw;
|
||||||
|
m_has_valid_subcode = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log_WarningPrint("SCSI reads failed, trying raw read...");
|
||||||
|
if (DoRawRead(track_1_lba))
|
||||||
{
|
{
|
||||||
// verify subcode
|
// verify subcode
|
||||||
if (VerifySCSIReadData(std::span<u8>(m_buffer.data(), SCSIReadCommandOutputSize(SCSIReadMode::Full)),
|
if (VerifySCSIReadData(std::span<u8>(m_buffer.data(), SCSIReadCommandOutputSize(SCSIReadMode::Full)),
|
||||||
|
@ -578,51 +623,7 @@ bool CDImageDeviceWin32::DetermineReadMode(bool try_sptd)
|
||||||
m_has_valid_subcode = true;
|
m_has_valid_subcode = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<u32> transfer_size;
|
|
||||||
|
|
||||||
Log_DevPrint("Trying SCSI read with full subcode...");
|
|
||||||
if (check_subcode && (transfer_size = DoSCSIRead(track_1_lba, SCSIReadMode::Full)).has_value())
|
|
||||||
{
|
|
||||||
if (VerifySCSIReadData(std::span<u8>(m_buffer.data(), transfer_size.value()), SCSIReadMode::Full, track_1_subq_lba))
|
|
||||||
{
|
|
||||||
Log_VerbosePrint("Using SCSI reads with subcode");
|
|
||||||
m_scsi_read_mode = SCSIReadMode::Full;
|
|
||||||
m_has_valid_subcode = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Log_WarningPrint("Full subcode failed, trying SCSI read with only subq...");
|
|
||||||
if (check_subcode && (transfer_size = DoSCSIRead(track_1_lba, SCSIReadMode::SubQOnly)).has_value())
|
|
||||||
{
|
|
||||||
if (VerifySCSIReadData(std::span<u8>(m_buffer.data(), transfer_size.value()), SCSIReadMode::SubQOnly,
|
|
||||||
track_1_subq_lba))
|
|
||||||
{
|
|
||||||
Log_VerbosePrint("Using SCSI reads with subq only");
|
|
||||||
m_scsi_read_mode = SCSIReadMode::SubQOnly;
|
|
||||||
m_has_valid_subcode = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// As a last ditch effort, try SCSI without subcode.
|
|
||||||
Log_WarningPrint("Subq only failed failed, trying SCSI without subcode...");
|
|
||||||
if ((transfer_size = DoSCSIRead(track_1_lba, SCSIReadMode::Raw)).has_value())
|
|
||||||
{
|
|
||||||
if (VerifySCSIReadData(std::span<u8>(m_buffer.data(), transfer_size.value()), SCSIReadMode::Raw, track_1_subq_lba))
|
|
||||||
{
|
|
||||||
Log_WarningPrint("Using SCSI raw reads, libcrypt games will not run correctly");
|
|
||||||
m_scsi_read_mode = SCSIReadMode::Raw;
|
|
||||||
m_has_valid_subcode = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Log_WarningPrint("Raw SCSI read failed, trying raw but ignoring subcode...");
|
|
||||||
if (DoRawRead(track_1_lba))
|
|
||||||
{
|
|
||||||
Log_WarningPrint("Using raw reads without subcode, libcrypt games will not run correctly");
|
Log_WarningPrint("Using raw reads without subcode, libcrypt games will not run correctly");
|
||||||
m_scsi_read_mode = SCSIReadMode::None;
|
m_scsi_read_mode = SCSIReadMode::None;
|
||||||
m_has_valid_subcode = false;
|
m_has_valid_subcode = false;
|
||||||
|
@ -726,7 +727,6 @@ private:
|
||||||
SCSIReadMode m_scsi_read_mode = SCSIReadMode::None;
|
SCSIReadMode m_scsi_read_mode = SCSIReadMode::None;
|
||||||
|
|
||||||
std::array<u8, RAW_SECTOR_SIZE + ALL_SUBCODE_SIZE> m_buffer;
|
std::array<u8, RAW_SECTOR_SIZE + ALL_SUBCODE_SIZE> m_buffer;
|
||||||
std::array<u8, SUBCHANNEL_BYTES_PER_FRAME> m_subq;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -814,7 +814,7 @@ bool CDImageDeviceLinux::Open(const char* filename, Error* error)
|
||||||
const TrackMode track_mode = control.data ? CDImage::TrackMode::Mode2Raw : CDImage::TrackMode::Audio;
|
const TrackMode track_mode = control.data ? CDImage::TrackMode::Mode2Raw : CDImage::TrackMode::Audio;
|
||||||
|
|
||||||
// TODO: How the hell do we handle pregaps here?
|
// TODO: How the hell do we handle pregaps here?
|
||||||
const u32 pregap_frames = (control.data && track_index == 0) ? 150 : 0;
|
const u32 pregap_frames = (track_index == 0) ? 150 : 0;
|
||||||
if (pregap_frames > 0)
|
if (pregap_frames > 0)
|
||||||
{
|
{
|
||||||
Index pregap_index = {};
|
Index pregap_index = {};
|
||||||
|
@ -917,8 +917,22 @@ bool CDImageDeviceLinux::ReadSubChannelQ(SubChannelQ* subq, const Index& index,
|
||||||
if (m_current_lba != disc_lba && !ReadSectorToBuffer(disc_lba))
|
if (m_current_lba != disc_lba && !ReadSectorToBuffer(disc_lba))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::memcpy(subq->data.data(), m_subq.data(), SUBCHANNEL_BYTES_PER_FRAME);
|
if (m_scsi_read_mode == SCSIReadMode::SubQOnly)
|
||||||
return true;
|
{
|
||||||
|
// copy out subq
|
||||||
|
std::memcpy(subq->data.data(), m_buffer.data() + RAW_SECTOR_SIZE, SUBCHANNEL_BYTES_PER_FRAME);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else // if (m_scsi_read_mode == SCSIReadMode::Full)
|
||||||
|
{
|
||||||
|
// need to deinterleave the subcode
|
||||||
|
u8 deinterleaved_subcode[ALL_SUBCODE_SIZE];
|
||||||
|
DeinterleaveSubcode(m_buffer.data() + RAW_SECTOR_SIZE, deinterleaved_subcode);
|
||||||
|
|
||||||
|
// P, Q, ...
|
||||||
|
std::memcpy(subq->data.data(), deinterleaved_subcode + SUBCHANNEL_BYTES_PER_FRAME, SUBCHANNEL_BYTES_PER_FRAME);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDImageDeviceLinux::HasNonStandardSubchannel() const
|
bool CDImageDeviceLinux::HasNonStandardSubchannel() const
|
||||||
|
@ -1007,19 +1021,6 @@ bool CDImageDeviceLinux::ReadSectorToBuffer(LBA lba)
|
||||||
Log_ErrorFmt("Read of LBA {} failed: only got {} of {} bytes", lba, size.value(), expected_size);
|
Log_ErrorFmt("Read of LBA {} failed: only got {} of {} bytes", lba, size.value(), expected_size);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_scsi_read_mode == SCSIReadMode::Full)
|
|
||||||
{
|
|
||||||
// need to deinterleave the subcode
|
|
||||||
u8 deinterleaved_subcode[ALL_SUBCODE_SIZE];
|
|
||||||
DeinterleaveSubcode(m_buffer.data() + RAW_SECTOR_SIZE, deinterleaved_subcode);
|
|
||||||
std::memcpy(&m_subq, deinterleaved_subcode + SUBCHANNEL_BYTES_PER_FRAME, sizeof(m_subq)); // P,Q
|
|
||||||
}
|
|
||||||
else if (m_scsi_read_mode == SCSIReadMode::SubQOnly)
|
|
||||||
{
|
|
||||||
// copy out subq
|
|
||||||
std::memcpy(&m_subq, m_buffer.data() + RAW_SECTOR_SIZE, sizeof(m_subq));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue