mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-29 09:05:41 +00:00
CDROM: Synthesize lead-out area and stop reading when reached
This commit is contained in:
parent
c67e877d82
commit
5b389ae13d
|
@ -167,10 +167,18 @@ bool CDImage::ReadRawSector(void* buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (m_current_index->track_number == LEAD_OUT_TRACK_NUMBER)
|
||||||
|
{
|
||||||
|
// Lead-out area.
|
||||||
|
std::fill(static_cast<u8*>(buffer), static_cast<u8*>(buffer) + RAW_SECTOR_SIZE, u8(0xAA));
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// This in an implicit pregap. Return silence.
|
// This in an implicit pregap. Return silence.
|
||||||
std::fill(static_cast<u8*>(buffer), static_cast<u8*>(buffer) + RAW_SECTOR_SIZE, u8(0));
|
std::fill(static_cast<u8*>(buffer), static_cast<u8*>(buffer) + RAW_SECTOR_SIZE, u8(0));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_position_on_disc++;
|
m_position_on_disc++;
|
||||||
m_position_in_index++;
|
m_position_in_index++;
|
||||||
|
@ -246,6 +254,16 @@ void CDImage::GenerateSubChannelQ(SubChannelQ* subq, const Index* index, u32 ind
|
||||||
subq->crc = SubChannelQ::ComputeCRC(subq->data);
|
subq->crc = SubChannelQ::ComputeCRC(subq->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CDImage::AddLeadOutIndex()
|
||||||
|
{
|
||||||
|
Index index = {};
|
||||||
|
index.start_lba_on_disc = m_lba_count;
|
||||||
|
index.length = LEAD_OUT_SECTOR_COUNT;
|
||||||
|
index.track_number = 0xAA;
|
||||||
|
index.index_number = 0;
|
||||||
|
m_indices.push_back(index);
|
||||||
|
}
|
||||||
|
|
||||||
u16 CDImage::SubChannelQ::ComputeCRC(const u8* data)
|
u16 CDImage::SubChannelQ::ComputeCRC(const u8* data)
|
||||||
{
|
{
|
||||||
static constexpr std::array<u16, 256> crc16_table = {
|
static constexpr std::array<u16, 256> crc16_table = {
|
||||||
|
|
|
@ -23,7 +23,13 @@ public:
|
||||||
FRAMES_PER_SECOND = 75, // "sectors", or "timecode frames" (not "channel frames")
|
FRAMES_PER_SECOND = 75, // "sectors", or "timecode frames" (not "channel frames")
|
||||||
SECONDS_PER_MINUTE = 60,
|
SECONDS_PER_MINUTE = 60,
|
||||||
FRAMES_PER_MINUTE = FRAMES_PER_SECOND * SECONDS_PER_MINUTE,
|
FRAMES_PER_MINUTE = FRAMES_PER_SECOND * SECONDS_PER_MINUTE,
|
||||||
SUBCHANNEL_BYTES_PER_FRAME = 12
|
SUBCHANNEL_BYTES_PER_FRAME = 12,
|
||||||
|
LEAD_OUT_SECTOR_COUNT = 6750
|
||||||
|
};
|
||||||
|
|
||||||
|
enum : u8
|
||||||
|
{
|
||||||
|
LEAD_OUT_TRACK_NUMBER = 0xAA
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ReadMode : u32
|
enum class ReadMode : u32
|
||||||
|
@ -235,6 +241,9 @@ protected:
|
||||||
/// Generates sub-channel Q from the given index and index-offset.
|
/// Generates sub-channel Q from the given index and index-offset.
|
||||||
void GenerateSubChannelQ(SubChannelQ* subq, const Index* index, u32 index_offset);
|
void GenerateSubChannelQ(SubChannelQ* subq, const Index* index, u32 index_offset);
|
||||||
|
|
||||||
|
/// Synthesis of lead-out data.
|
||||||
|
void AddLeadOutIndex();
|
||||||
|
|
||||||
std::string m_filename;
|
std::string m_filename;
|
||||||
u32 m_lba_count = 0;
|
u32 m_lba_count = 0;
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,8 @@ bool CDImageBin::Open(const char* filename)
|
||||||
m_tracks.push_back(
|
m_tracks.push_back(
|
||||||
Track{static_cast<u32>(1), data_index.start_lba_on_disc, static_cast<u32>(0), m_lba_count, mode, control});
|
Track{static_cast<u32>(1), data_index.start_lba_on_disc, static_cast<u32>(0), m_lba_count, mode, control});
|
||||||
|
|
||||||
|
AddLeadOutIndex();
|
||||||
|
|
||||||
m_sbi.LoadSBI(ReplaceExtension(filename, "sbi").c_str());
|
m_sbi.LoadSBI(ReplaceExtension(filename, "sbi").c_str());
|
||||||
|
|
||||||
return Seek(1, Position{0, 0, 0});
|
return Seek(1, Position{0, 0, 0});
|
||||||
|
|
|
@ -222,6 +222,7 @@ bool CDImageCHD::Open(const char* filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lba_count = disc_lba;
|
m_lba_count = disc_lba;
|
||||||
|
AddLeadOutIndex();
|
||||||
|
|
||||||
m_sbi.LoadSBI(FileSystem::ReplaceExtension(filename, "sbi").c_str());
|
m_sbi.LoadSBI(FileSystem::ReplaceExtension(filename, "sbi").c_str());
|
||||||
|
|
||||||
|
|
|
@ -210,6 +210,7 @@ bool CDImageCueSheet::OpenAndParse(const char* filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lba_count = disc_lba;
|
m_lba_count = disc_lba;
|
||||||
|
AddLeadOutIndex();
|
||||||
|
|
||||||
m_sbi.LoadSBI(FileSystem::ReplaceExtension(filename, "sbi").c_str());
|
m_sbi.LoadSBI(FileSystem::ReplaceExtension(filename, "sbi").c_str());
|
||||||
|
|
||||||
|
|
|
@ -1448,6 +1448,17 @@ void CDROM::DoTOCRead()
|
||||||
SetAsyncInterrupt(Interrupt::Complete);
|
SetAsyncInterrupt(Interrupt::Complete);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CDROM::StopReadingWithDataEnd()
|
||||||
|
{
|
||||||
|
ClearAsyncInterrupt();
|
||||||
|
m_async_response_fifo.Push(m_secondary_status.bits);
|
||||||
|
SetAsyncInterrupt(Interrupt::DataEnd);
|
||||||
|
|
||||||
|
m_secondary_status.ClearActiveBits();
|
||||||
|
m_drive_state = DriveState::Idle;
|
||||||
|
m_drive_event->Deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
void CDROM::DoSectorRead()
|
void CDROM::DoSectorRead()
|
||||||
{
|
{
|
||||||
if (!m_reader.WaitForReadToComplete())
|
if (!m_reader.WaitForReadToComplete())
|
||||||
|
@ -1456,6 +1467,13 @@ void CDROM::DoSectorRead()
|
||||||
// TODO: Error handling
|
// TODO: Error handling
|
||||||
// TODO: Check SubQ checksum.
|
// TODO: Check SubQ checksum.
|
||||||
const CDImage::SubChannelQ& subq = m_reader.GetSectorSubQ();
|
const CDImage::SubChannelQ& subq = m_reader.GetSectorSubQ();
|
||||||
|
if (subq.track_number_bcd == CDImage::LEAD_OUT_TRACK_NUMBER)
|
||||||
|
{
|
||||||
|
Log_DevPrintf("Read reached lead-out area of disc at LBA %u, pausing", m_reader.GetLastReadSector());
|
||||||
|
StopReadingWithDataEnd();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const bool is_data_sector = subq.control.data;
|
const bool is_data_sector = subq.control.data;
|
||||||
if (!is_data_sector)
|
if (!is_data_sector)
|
||||||
{
|
{
|
||||||
|
@ -1471,13 +1489,7 @@ void CDROM::DoSectorRead()
|
||||||
Log_DevPrintf("Auto pause at the end of track %u (LBA %u)", m_play_track_number_bcd,
|
Log_DevPrintf("Auto pause at the end of track %u (LBA %u)", m_play_track_number_bcd,
|
||||||
m_reader.GetLastReadSector());
|
m_reader.GetLastReadSector());
|
||||||
|
|
||||||
ClearAsyncInterrupt();
|
StopReadingWithDataEnd();
|
||||||
m_async_response_fifo.Push(m_secondary_status.bits);
|
|
||||||
SetAsyncInterrupt(Interrupt::DataEnd);
|
|
||||||
|
|
||||||
m_secondary_status.ClearActiveBits();
|
|
||||||
m_drive_state = DriveState::Idle;
|
|
||||||
m_drive_event->Deactivate();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,6 +234,7 @@ private:
|
||||||
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 StopReadingWithDataEnd();
|
||||||
void BeginSeeking(bool logical, bool read_after_seek, bool play_after_seek);
|
void BeginSeeking(bool logical, bool read_after_seek, bool play_after_seek);
|
||||||
void ResetCurrentXAFile();
|
void ResetCurrentXAFile();
|
||||||
void LoadDataFIFO();
|
void LoadDataFIFO();
|
||||||
|
|
Loading…
Reference in a new issue