testing
This commit is contained in:
parent
571a773b29
commit
c883779595
|
@ -704,9 +704,6 @@ void CDROM::DeliverAsyncInterrupt()
|
|||
Assert(m_pending_async_interrupt != 0 && !HasPendingInterrupt());
|
||||
Log_DebugPrintf("Delivering async interrupt %u", m_pending_async_interrupt);
|
||||
|
||||
if (m_pending_async_interrupt == static_cast<u8>(Interrupt::DataReady))
|
||||
m_current_read_sector_buffer = m_current_write_sector_buffer;
|
||||
|
||||
m_response_fifo.Clear();
|
||||
m_response_fifo.PushFromQueue(&m_async_response_fifo);
|
||||
m_interrupt_flag_register = m_pending_async_interrupt;
|
||||
|
@ -1812,8 +1809,11 @@ void CDROM::BeginReading(TickCount ticks_late /* = 0 */, bool after_seek /* = fa
|
|||
m_drive_state = DriveState::Reading;
|
||||
m_drive_event->SetInterval(ticks);
|
||||
m_drive_event->Schedule(first_sector_ticks);
|
||||
m_current_read_sector_buffer = 0;
|
||||
m_current_read_sector_buffer = NUM_SECTOR_BUFFERS - 1;
|
||||
m_current_write_sector_buffer = 0;
|
||||
m_deliver_sector_buffer = 0;
|
||||
m_buffered_sector_count = 0;
|
||||
m_buffered_sectors_remaining = NUM_SECTORS_TO_BUFFER;
|
||||
|
||||
m_requested_lba = m_current_lba;
|
||||
m_reader.QueueReadSector(m_requested_lba);
|
||||
|
@ -1855,8 +1855,11 @@ void CDROM::BeginPlaying(u8 track, TickCount ticks_late /* = 0 */, bool after_se
|
|||
m_drive_state = DriveState::Playing;
|
||||
m_drive_event->SetInterval(ticks);
|
||||
m_drive_event->Schedule(first_sector_ticks);
|
||||
m_current_read_sector_buffer = 0;
|
||||
m_current_read_sector_buffer = NUM_SECTOR_BUFFERS - 1;
|
||||
m_current_write_sector_buffer = 0;
|
||||
m_deliver_sector_buffer = 0;
|
||||
m_buffered_sector_count = 0;
|
||||
m_buffered_sectors_remaining = NUM_SECTORS_TO_BUFFER;
|
||||
|
||||
m_requested_lba = m_current_lba;
|
||||
m_reader.QueueReadSector(m_requested_lba);
|
||||
|
@ -2066,9 +2069,9 @@ bool CDROM::CompleteSeek()
|
|||
{
|
||||
if (logical)
|
||||
{
|
||||
ProcessDataSectorHeader(m_reader.GetSectorBuffer().data());
|
||||
seek_okay = (m_last_sector_header.minute == seek_mm && m_last_sector_header.second == seek_ss &&
|
||||
m_last_sector_header.frame == seek_ff);
|
||||
const CDImage::SectorHeader* header =
|
||||
reinterpret_cast<const CDImage::SectorHeader*>(m_reader.GetSectorBuffer().data() + SECTOR_SYNC_SIZE);
|
||||
seek_okay = (header->minute == seek_mm && header->second == seek_ss && header->frame == seek_ff);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2320,15 +2323,11 @@ void CDROM::DoSectorRead()
|
|||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessDataSectorHeader(m_reader.GetSectorBuffer().data());
|
||||
}
|
||||
|
||||
u32 next_sector = m_current_lba + 1u;
|
||||
if (is_data_sector && m_drive_state == DriveState::Reading)
|
||||
{
|
||||
ProcessDataSector(m_reader.GetSectorBuffer().data(), subq);
|
||||
EnqueueDataSector(m_reader.GetSectorBuffer().data());
|
||||
}
|
||||
else if (!is_data_sector &&
|
||||
(m_drive_state == DriveState::Playing || (m_drive_state == DriveState::Reading && m_mode.cdda)))
|
||||
|
@ -2348,6 +2347,8 @@ void CDROM::DoSectorRead()
|
|||
is_data_sector ? "data" : "audio", is_data_sector ? "reading" : "playing");
|
||||
}
|
||||
|
||||
ProcessDataSector();
|
||||
|
||||
m_requested_lba = next_sector;
|
||||
m_reader.QueueReadSector(m_requested_lba);
|
||||
}
|
||||
|
@ -2355,60 +2356,88 @@ void CDROM::DoSectorRead()
|
|||
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_subheader, &raw_sector[SECTOR_SYNC_SIZE + sizeof(m_last_sector_header)],
|
||||
sizeof(m_last_sector_subheader));
|
||||
std::memcpy(&m_last_sector_subheader, &raw_sector[SECTOR_SYNC_SIZE + sizeof(m_last_sector_header)], sizeof(m_last_sector_subheader));
|
||||
m_last_sector_header_valid = true;
|
||||
}
|
||||
|
||||
void CDROM::ProcessDataSector(const u8* raw_sector, const CDImage::SubChannelQ& subq)
|
||||
void CDROM::EnqueueDataSector(const u8* raw_sector)
|
||||
{
|
||||
const u32 sb_num = (m_current_write_sector_buffer + 1) % NUM_SECTOR_BUFFERS;
|
||||
Log_DevPrintf("Read sector %u: mode %u submode 0x%02X into buffer %u", m_current_lba,
|
||||
ZeroExtend32(m_last_sector_header.sector_mode), ZeroExtend32(m_last_sector_subheader.submode.bits),
|
||||
sb_num);
|
||||
|
||||
if (m_mode.xa_enable && m_last_sector_header.sector_mode == 2)
|
||||
const CDImage::SectorHeader* header =
|
||||
reinterpret_cast<const CDImage::SectorHeader*>(m_reader.GetSectorBuffer().data() + SECTOR_SYNC_SIZE);
|
||||
const CDXA::XASubHeader* subheader = reinterpret_cast<const CDXA::XASubHeader*>(
|
||||
m_reader.GetSectorBuffer().data() + SECTOR_SYNC_SIZE + sizeof(CDImage::SectorHeader));
|
||||
if (header->sector_mode != 2)
|
||||
{
|
||||
if (m_last_sector_subheader.submode.realtime && m_last_sector_subheader.submode.audio)
|
||||
{
|
||||
ProcessXAADPCMSector(raw_sector, subq);
|
||||
|
||||
// Audio+realtime sectors aren't delivered to the CPU.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: How does XA relate to this buffering?
|
||||
SectorBuffer* sb = &m_sector_buffers[sb_num];
|
||||
if (sb->size > 0)
|
||||
{
|
||||
Log_DevPrintf("Sector buffer %u was not read, previous sector dropped",
|
||||
(m_current_write_sector_buffer - 1) % NUM_SECTOR_BUFFERS);
|
||||
Log_WarningPrintf("Ignoring non-mode2 sector at %u", m_current_lba);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_mode.ignore_bit)
|
||||
Log_WarningPrintf("SetMode.4 bit set on read of sector %u", m_current_lba);
|
||||
|
||||
if (m_mode.read_raw_sector)
|
||||
const u32 sb_num = m_current_write_sector_buffer;
|
||||
m_current_write_sector_buffer = (m_current_write_sector_buffer + 1) % NUM_SECTOR_BUFFERS;
|
||||
|
||||
Log_DevPrintf("Enqueue data sector %u: %02X:%02X:%02X mode %u submode 0x%02X into buffer %u", m_current_lba,
|
||||
ZeroExtend32(header->minute), ZeroExtend32(header->second), ZeroExtend32(header->frame),
|
||||
ZeroExtend32(header->sector_mode), ZeroExtend32(subheader->submode.bits), sb_num);
|
||||
|
||||
SectorBuffer* sb = &m_sector_buffers[sb_num];
|
||||
if (sb->size > 0)
|
||||
Log_DevPrintf("Sector buffer %u was not read, previous sector dropped", m_current_write_sector_buffer);
|
||||
|
||||
std::memcpy(sb->data.data(), raw_sector, CDImage::RAW_SECTOR_SIZE);
|
||||
sb->size = CDImage::RAW_SECTOR_SIZE;
|
||||
|
||||
m_buffered_sector_count++;
|
||||
Log_DevPrintf("[%u] %u sectors buffered...", m_current_lba, m_buffered_sector_count);
|
||||
}
|
||||
|
||||
void CDROM::ProcessDataSector()
|
||||
{
|
||||
// Wait until we have at least two sectors buffered before we process any.
|
||||
// This simulates the delay between subq and data present on the hardware, where it's doing ECC and other processing.
|
||||
if (m_buffered_sectors_remaining > 0 && (m_buffered_sectors_remaining--) > 0)
|
||||
{
|
||||
std::memcpy(sb->data.data(), raw_sector + SECTOR_SYNC_SIZE, RAW_SECTOR_OUTPUT_SIZE);
|
||||
sb->size = RAW_SECTOR_OUTPUT_SIZE;
|
||||
Log_DebugPrintf("Only %u sectors buffered, waiting...", m_buffered_sector_count);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
// Anything to process?
|
||||
if (m_buffered_sector_count == 0)
|
||||
return;
|
||||
|
||||
// Add a delay for the next sector if we're not full
|
||||
m_buffered_sector_count--;
|
||||
if (m_buffered_sector_count < NUM_SECTORS_TO_BUFFER)
|
||||
m_buffered_sectors_remaining++;
|
||||
|
||||
m_current_read_sector_buffer = (m_current_read_sector_buffer + 1) % NUM_SECTOR_BUFFERS;
|
||||
const u32 sb_num = m_current_read_sector_buffer;
|
||||
|
||||
SectorBuffer* sb = &m_sector_buffers[sb_num];
|
||||
if (sb->size == 0)
|
||||
{
|
||||
// TODO: This should actually depend on the mode...
|
||||
if (m_last_sector_header.sector_mode != 2)
|
||||
Log_WarningPrintf("Empty sector buffer %u?!", sb_num);
|
||||
return;
|
||||
}
|
||||
|
||||
// Read out and store header (for GetLocL).
|
||||
ProcessDataSectorHeader(sb->data.data());
|
||||
|
||||
// Non-mode 2 sectors aren't buffered.
|
||||
if (m_mode.xa_enable /*&& m_last_sector_header.sector_mode == 2*/)
|
||||
{
|
||||
if (m_last_sector_subheader.submode.realtime && m_last_sector_subheader.submode.audio)
|
||||
{
|
||||
Log_WarningPrintf("Ignoring non-mode2 sector at %u", m_current_lba);
|
||||
ProcessXAADPCMSector(sb->data.data());
|
||||
|
||||
// Audio+realtime sectors aren't delivered to the CPU.
|
||||
sb->size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
std::memcpy(sb->data.data(), raw_sector + CDImage::SECTOR_SYNC_SIZE + 12, DATA_SECTOR_OUTPUT_SIZE);
|
||||
sb->size = DATA_SECTOR_OUTPUT_SIZE;
|
||||
}
|
||||
|
||||
m_current_write_sector_buffer = sb_num;
|
||||
|
||||
// Deliver to CPU
|
||||
if (HasPendingAsyncInterrupt())
|
||||
{
|
||||
|
@ -2418,13 +2447,20 @@ void CDROM::ProcessDataSector(const u8* raw_sector, const CDImage::SubChannelQ&
|
|||
|
||||
if (HasPendingInterrupt())
|
||||
{
|
||||
const u32 sectors_missed = (m_current_write_sector_buffer - m_current_read_sector_buffer) % NUM_SECTOR_BUFFERS;
|
||||
const u32 sectors_missed = (sb_num - m_deliver_sector_buffer) % NUM_SECTOR_BUFFERS;
|
||||
if (sectors_missed > 1)
|
||||
Log_WarningPrintf("Interrupt not processed in time, missed %u sectors", sectors_missed - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This sector is now ready for delivery.
|
||||
Log_DevPrintf("Deliver sector %02X:%02X:%02X to CPU", ZeroExtend32(m_last_sector_header.minute),
|
||||
ZeroExtend32(m_last_sector_header.second), ZeroExtend32(m_last_sector_header.frame));
|
||||
m_deliver_sector_buffer = sb_num;
|
||||
|
||||
m_async_response_fifo.Push(m_secondary_status.bits);
|
||||
SetAsyncInterrupt(Interrupt::DataReady);
|
||||
m_async_response_fifo.Push(m_secondary_status.bits);
|
||||
SetAsyncInterrupt(Interrupt::DataReady);
|
||||
}
|
||||
}
|
||||
|
||||
static std::array<std::array<s16, 29>, 7> s_zigzag_table = {
|
||||
|
@ -2531,7 +2567,7 @@ void CDROM::ResetAudioDecoder()
|
|||
m_audio_fifo.Clear();
|
||||
}
|
||||
|
||||
void CDROM::ProcessXAADPCMSector(const u8* raw_sector, const CDImage::SubChannelQ& subq)
|
||||
void CDROM::ProcessXAADPCMSector(const u8* raw_sector)
|
||||
{
|
||||
// Check for automatic ADPCM filter.
|
||||
if (m_mode.xa_filter && (m_last_sector_subheader.file_number != m_xa_filter_file_number ||
|
||||
|
@ -2719,24 +2755,31 @@ void CDROM::LoadDataFIFO()
|
|||
}
|
||||
|
||||
// any data to load?
|
||||
SectorBuffer& sb = m_sector_buffers[m_current_read_sector_buffer];
|
||||
SectorBuffer& sb = m_sector_buffers[m_deliver_sector_buffer];
|
||||
if (sb.size == 0)
|
||||
{
|
||||
Log_WarningPrintf("Attempting to load empty sector buffer");
|
||||
m_data_fifo.PushRange(sb.data.data(), RAW_SECTOR_OUTPUT_SIZE);
|
||||
m_data_fifo.PushRange(sb.data.data() + SECTOR_SYNC_SIZE, RAW_SECTOR_OUTPUT_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data_fifo.PushRange(sb.data.data(), sb.size);
|
||||
if (m_mode.read_raw_sector)
|
||||
m_data_fifo.PushRange(sb.data.data() + SECTOR_SYNC_SIZE, RAW_SECTOR_OUTPUT_SIZE);
|
||||
else
|
||||
m_data_fifo.PushRange(sb.data.data() + SECTOR_SYNC_SIZE + 12, DATA_SECTOR_OUTPUT_SIZE);
|
||||
sb.size = 0;
|
||||
}
|
||||
|
||||
Log_DebugPrintf("Loaded %u bytes to data FIFO from buffer %u", m_data_fifo.GetSize(), m_current_read_sector_buffer);
|
||||
const CDImage::SectorHeader* header = reinterpret_cast<const CDImage::SectorHeader*>(sb.data.data() + SECTOR_SYNC_SIZE);
|
||||
Log_DevPrintf("Loaded %u bytes to data FIFO from buffer %u [%02X:%02X:%02X]", m_data_fifo.GetSize(),
|
||||
m_deliver_sector_buffer, header->minute, header->second, header->frame);
|
||||
|
||||
SectorBuffer& next_sb = m_sector_buffers[m_current_write_sector_buffer];
|
||||
// FIXME
|
||||
SectorBuffer& next_sb = m_sector_buffers[m_current_read_sector_buffer];
|
||||
if (next_sb.size > 0)
|
||||
{
|
||||
Log_DevPrintf("Sending additional INT1 for missed sector in buffer %u", m_current_write_sector_buffer);
|
||||
Log_DevPrintf("Sending additional INT1 for missed sector in buffer %u", m_current_read_sector_buffer);
|
||||
m_deliver_sector_buffer = m_current_read_sector_buffer;
|
||||
m_async_response_fifo.Push(m_secondary_status.bits);
|
||||
SetAsyncInterrupt(Interrupt::DataReady);
|
||||
}
|
||||
|
|
|
@ -87,7 +87,9 @@ private:
|
|||
MOTOR_ON_RESPONSE_TICKS = 400000,
|
||||
|
||||
MAX_FAST_FORWARD_RATE = 12,
|
||||
FAST_FORWARD_RATE_STEP = 4
|
||||
FAST_FORWARD_RATE_STEP = 4,
|
||||
|
||||
NUM_SECTORS_TO_BUFFER = 2
|
||||
};
|
||||
|
||||
static constexpr u8 INTERRUPT_REGISTER_MASK = 0x1F;
|
||||
|
@ -314,9 +316,10 @@ private:
|
|||
void DoSpeedChangeOrImplicitTOCReadComplete();
|
||||
void DoIDRead();
|
||||
void DoSectorRead();
|
||||
void EnqueueDataSector(const u8* raw_sector);
|
||||
void ProcessDataSector();
|
||||
void ProcessDataSectorHeader(const u8* raw_sector);
|
||||
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);
|
||||
void ProcessCDDASector(const u8* raw_sector, const CDImage::SubChannelQ& subq);
|
||||
void StopReadingWithDataEnd();
|
||||
void StartMotor();
|
||||
|
@ -395,12 +398,15 @@ private:
|
|||
|
||||
struct SectorBuffer
|
||||
{
|
||||
HeapArray<u8, RAW_SECTOR_OUTPUT_SIZE> data;
|
||||
HeapArray<u8, CDImage::RAW_SECTOR_SIZE> data;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
u32 m_current_read_sector_buffer = 0;
|
||||
u32 m_current_write_sector_buffer = 0;
|
||||
u32 m_deliver_sector_buffer = 0;
|
||||
u32 m_buffered_sector_count = 0;
|
||||
u32 m_buffered_sectors_remaining = 0;
|
||||
std::array<SectorBuffer, NUM_SECTOR_BUFFERS> m_sector_buffers;
|
||||
|
||||
CDROMAsyncReader m_reader;
|
||||
|
|
Loading…
Reference in New Issue