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
|
||||
{
|
||||
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.
|
||||
std::fill(static_cast<u8*>(buffer), static_cast<u8*>(buffer) + RAW_SECTOR_SIZE, u8(0));
|
||||
}
|
||||
}
|
||||
|
||||
m_position_on_disc++;
|
||||
m_position_in_index++;
|
||||
|
@ -246,6 +254,16 @@ void CDImage::GenerateSubChannelQ(SubChannelQ* subq, const Index* index, u32 ind
|
|||
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)
|
||||
{
|
||||
static constexpr std::array<u16, 256> crc16_table = {
|
||||
|
|
|
@ -23,7 +23,13 @@ public:
|
|||
FRAMES_PER_SECOND = 75, // "sectors", or "timecode frames" (not "channel frames")
|
||||
SECONDS_PER_MINUTE = 60,
|
||||
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
|
||||
|
@ -235,6 +241,9 @@ protected:
|
|||
/// Generates sub-channel Q from the given index and index-offset.
|
||||
void GenerateSubChannelQ(SubChannelQ* subq, const Index* index, u32 index_offset);
|
||||
|
||||
/// Synthesis of lead-out data.
|
||||
void AddLeadOutIndex();
|
||||
|
||||
std::string m_filename;
|
||||
u32 m_lba_count = 0;
|
||||
|
||||
|
|
|
@ -99,6 +99,8 @@ bool CDImageBin::Open(const char* filename)
|
|||
m_tracks.push_back(
|
||||
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());
|
||||
|
||||
return Seek(1, Position{0, 0, 0});
|
||||
|
|
|
@ -222,6 +222,7 @@ bool CDImageCHD::Open(const char* filename)
|
|||
}
|
||||
|
||||
m_lba_count = disc_lba;
|
||||
AddLeadOutIndex();
|
||||
|
||||
m_sbi.LoadSBI(FileSystem::ReplaceExtension(filename, "sbi").c_str());
|
||||
|
||||
|
|
|
@ -210,6 +210,7 @@ bool CDImageCueSheet::OpenAndParse(const char* filename)
|
|||
}
|
||||
|
||||
m_lba_count = disc_lba;
|
||||
AddLeadOutIndex();
|
||||
|
||||
m_sbi.LoadSBI(FileSystem::ReplaceExtension(filename, "sbi").c_str());
|
||||
|
||||
|
|
|
@ -1448,6 +1448,17 @@ void CDROM::DoTOCRead()
|
|||
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()
|
||||
{
|
||||
if (!m_reader.WaitForReadToComplete())
|
||||
|
@ -1456,6 +1467,13 @@ void CDROM::DoSectorRead()
|
|||
// TODO: Error handling
|
||||
// TODO: Check SubQ checksum.
|
||||
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;
|
||||
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,
|
||||
m_reader.GetLastReadSector());
|
||||
|
||||
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();
|
||||
StopReadingWithDataEnd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,6 +234,7 @@ private:
|
|||
void ProcessDataSector(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 StopReadingWithDataEnd();
|
||||
void BeginSeeking(bool logical, bool read_after_seek, bool play_after_seek);
|
||||
void ResetCurrentXAFile();
|
||||
void LoadDataFIFO();
|
||||
|
|
Loading…
Reference in New Issue