mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-12-01 18:15:41 +00:00
CDROM: Detection of XA audio sectors
This commit is contained in:
parent
8b4ec87055
commit
40dceacc7c
|
@ -123,7 +123,7 @@ u8 CDROM::ReadRegister(u32 offset)
|
||||||
switch (offset)
|
switch (offset)
|
||||||
{
|
{
|
||||||
case 0: // status register
|
case 0: // status register
|
||||||
Log_DebugPrintf("CDROM read status register <- 0x%08X", m_status.bits);
|
Log_TracePrintf("CDROM read status register <- 0x%08X", m_status.bits);
|
||||||
return m_status.bits;
|
return m_status.bits;
|
||||||
|
|
||||||
case 1: // always response FIFO
|
case 1: // always response FIFO
|
||||||
|
@ -184,7 +184,7 @@ void CDROM::WriteRegister(u32 offset, u8 value)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
Log_DebugPrintf("CDROM status register <- 0x%02X", ZeroExtend32(value));
|
Log_TracePrintf("CDROM status register <- 0x%02X", ZeroExtend32(value));
|
||||||
m_status.bits = (m_status.bits & static_cast<u8>(~3)) | (value & u8(3));
|
m_status.bits = (m_status.bits & static_cast<u8>(~3)) | (value & u8(3));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -277,16 +277,7 @@ void CDROM::WriteRegister(u32 offset, u8 value)
|
||||||
Assert(!rr.SMEN);
|
Assert(!rr.SMEN);
|
||||||
if (rr.BFRD)
|
if (rr.BFRD)
|
||||||
{
|
{
|
||||||
// any data to load?
|
LoadDataFIFO();
|
||||||
if (m_sector_buffer.empty())
|
|
||||||
{
|
|
||||||
Log_DevPrintf("Attempting to load empty sector buffer");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log_DebugPrintf("Loading data FIFO");
|
|
||||||
m_data_fifo.PushRange(m_sector_buffer.data(), static_cast<u32>(m_sector_buffer.size()));
|
|
||||||
m_sector_buffer.clear();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -361,7 +352,7 @@ u32 CDROM::DMARead()
|
||||||
m_data_fifo.Clear();
|
m_data_fifo.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log_DebugPrintf("DMA Read -> 0x%08X", data);
|
// Log_DebugPrintf("DMA Read -> 0x%08X (%u remaining)", data, m_data_fifo.GetSize());
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -755,19 +746,44 @@ void CDROM::DoSectorRead()
|
||||||
// return;
|
// return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log_DevPrintf("Reading sector %llu", m_media->GetCurrentLBA());
|
|
||||||
|
|
||||||
// TODO: Error handling
|
// TODO: Error handling
|
||||||
// TODO: Sector buffer should be two sectors?
|
// TODO: Sector buffer should be two sectors?
|
||||||
Assert(!m_mode.ignore_bit);
|
Assert(!m_mode.ignore_bit);
|
||||||
const u32 size =
|
m_sector_buffer.resize(CDImage::RAW_SECTOR_SIZE);
|
||||||
m_mode.read_raw_sector ? (CDImage::RAW_SECTOR_SIZE - CDImage::SECTOR_SYNC_SIZE) : CDImage::DATA_SECTOR_SIZE;
|
m_media->Read(CDImage::ReadMode::RawSector, 1, m_sector_buffer.data());
|
||||||
m_sector_buffer.resize(size);
|
Log_DevPrintf("Read sector %llu: mode %u submode 0x%02X", m_media->GetCurrentLBA(), ZeroExtend32(m_sector_buffer[15]),
|
||||||
m_media->Read(m_mode.read_raw_sector ? CDImage::ReadMode::RawNoSync : CDImage::ReadMode::DataOnly, 1,
|
ZeroExtend32(m_sector_buffer[18]));
|
||||||
m_sector_buffer.data());
|
|
||||||
|
bool pass_to_cpu = true;
|
||||||
|
if (m_mode.xa_enable)
|
||||||
|
{
|
||||||
|
const CDSectorHeader* sh =
|
||||||
|
reinterpret_cast<const CDSectorHeader*>(m_sector_buffer.data() + CDImage::SECTOR_SYNC_SIZE);
|
||||||
|
if (sh->sector_mode == 2)
|
||||||
|
{
|
||||||
|
const XASubHeader* xsh = reinterpret_cast<const XASubHeader*>(m_sector_buffer.data() + CDImage::SECTOR_SYNC_SIZE +
|
||||||
|
sizeof(CDSectorHeader));
|
||||||
|
if (xsh->submode.realtime && xsh->submode.audio)
|
||||||
|
{
|
||||||
|
// TODO: Decode audio sector. Do we still transfer this to the CPU?
|
||||||
|
Log_WarningPrintf("Decode CD-XA audio sector");
|
||||||
|
m_sector_buffer.clear();
|
||||||
|
pass_to_cpu = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xsh->submode.eof)
|
||||||
|
{
|
||||||
|
Log_WarningPrintf("End of CD-XA file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pass_to_cpu)
|
||||||
|
{
|
||||||
m_response_fifo.Push(m_secondary_status.bits);
|
m_response_fifo.Push(m_secondary_status.bits);
|
||||||
SetInterrupt(Interrupt::INT1);
|
SetInterrupt(Interrupt::INT1);
|
||||||
UpdateStatusRegister();
|
UpdateStatusRegister();
|
||||||
|
}
|
||||||
|
|
||||||
m_sector_read_remaining_ticks += GetTicksForRead();
|
m_sector_read_remaining_ticks += GetTicksForRead();
|
||||||
m_system->SetDowncount(m_sector_read_remaining_ticks);
|
m_system->SetDowncount(m_sector_read_remaining_ticks);
|
||||||
|
@ -782,3 +798,26 @@ void CDROM::StopReading()
|
||||||
m_secondary_status.reading = false;
|
m_secondary_status.reading = false;
|
||||||
m_reading = false;
|
m_reading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CDROM::LoadDataFIFO()
|
||||||
|
{
|
||||||
|
// any data to load?
|
||||||
|
if (m_sector_buffer.empty())
|
||||||
|
{
|
||||||
|
Log_DevPrintf("Attempting to load empty sector buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_mode.read_raw_sector)
|
||||||
|
{
|
||||||
|
m_data_fifo.PushRange(m_sector_buffer.data() + CDImage::SECTOR_SYNC_SIZE,
|
||||||
|
CDImage::RAW_SECTOR_SIZE - CDImage::SECTOR_SYNC_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_data_fifo.PushRange(m_sector_buffer.data() + CDImage::SECTOR_SYNC_SIZE + 12, CDImage::DATA_SECTOR_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log_DebugPrintf("Loaded %u bytes to data FIFO", m_data_fifo.GetSize());
|
||||||
|
m_sector_buffer.clear();
|
||||||
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ private:
|
||||||
BitField<u8, bool, 3, 1> xa_filter;
|
BitField<u8, bool, 3, 1> xa_filter;
|
||||||
BitField<u8, bool, 4, 1> ignore_bit;
|
BitField<u8, bool, 4, 1> ignore_bit;
|
||||||
BitField<u8, bool, 5, 1> read_raw_sector;
|
BitField<u8, bool, 5, 1> read_raw_sector;
|
||||||
BitField<u8, bool, 6, 1> xa_adpcm;
|
BitField<u8, bool, 6, 1> xa_enable;
|
||||||
BitField<u8, bool, 7, 1> double_speed;
|
BitField<u8, bool, 7, 1> double_speed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -146,6 +146,41 @@ private:
|
||||||
BitField<u8, bool, 7, 1> BFRD;
|
BitField<u8, bool, 7, 1> BFRD;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CDSectorHeader
|
||||||
|
{
|
||||||
|
u8 minute;
|
||||||
|
u8 second;
|
||||||
|
u8 frame;
|
||||||
|
u8 sector_mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct XASubHeader
|
||||||
|
{
|
||||||
|
u8 file_number;
|
||||||
|
u8 channel_number;
|
||||||
|
union Submode
|
||||||
|
{
|
||||||
|
u8 bits;
|
||||||
|
BitField<u8, bool, 0, 1> eor;
|
||||||
|
BitField<u8, bool, 1, 1> video;
|
||||||
|
BitField<u8, bool, 2, 1> audio;
|
||||||
|
BitField<u8, bool, 3, 1> data;
|
||||||
|
BitField<u8, bool, 4, 1> trigger;
|
||||||
|
BitField<u8, bool, 5, 1> form2;
|
||||||
|
BitField<u8, bool, 6, 1> realtime;
|
||||||
|
BitField<u8, bool, 7, 1> eof;
|
||||||
|
} submode;
|
||||||
|
union Codinginfo
|
||||||
|
{
|
||||||
|
u8 bits;
|
||||||
|
|
||||||
|
BitField<u8, u8, 0, 2> mono_stereo;
|
||||||
|
BitField<u8, u8, 2, 2> sample_rate;
|
||||||
|
BitField<u8, u8, 4, 2> bits_per_sample;
|
||||||
|
BitField<u8, bool, 6, 1> emphasis;
|
||||||
|
} codinginfo;
|
||||||
|
};
|
||||||
|
|
||||||
bool HasPendingInterrupt() const { return m_interrupt_flag_register != 0; }
|
bool HasPendingInterrupt() const { return m_interrupt_flag_register != 0; }
|
||||||
void SetInterrupt(Interrupt interrupt);
|
void SetInterrupt(Interrupt interrupt);
|
||||||
void PushStatResponse(Interrupt interrupt = Interrupt::ACK);
|
void PushStatResponse(Interrupt interrupt = Interrupt::ACK);
|
||||||
|
@ -161,6 +196,7 @@ private:
|
||||||
void BeginReading();
|
void BeginReading();
|
||||||
void DoSectorRead();
|
void DoSectorRead();
|
||||||
void StopReading();
|
void StopReading();
|
||||||
|
void LoadDataFIFO();
|
||||||
|
|
||||||
System* m_system = nullptr;
|
System* m_system = nullptr;
|
||||||
DMA* m_dma = nullptr;
|
DMA* m_dma = nullptr;
|
||||||
|
|
|
@ -92,12 +92,12 @@ void DMA::WriteRegister(u32 offset, u32 value)
|
||||||
case 0x00:
|
case 0x00:
|
||||||
{
|
{
|
||||||
state.base_address = value & ADDRESS_MASK;
|
state.base_address = value & ADDRESS_MASK;
|
||||||
Log_DebugPrintf("DMA channel %u base address <- 0x%08X", channel_index, state.base_address);
|
Log_TracePrintf("DMA channel %u base address <- 0x%08X", channel_index, state.base_address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case 0x04:
|
case 0x04:
|
||||||
{
|
{
|
||||||
Log_DebugPrintf("DMA channel %u block control <- 0x%08X", channel_index, value);
|
Log_TracePrintf("DMA channel %u block control <- 0x%08X", channel_index, value);
|
||||||
state.block_control.bits = value;
|
state.block_control.bits = value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ void DMA::WriteRegister(u32 offset, u32 value)
|
||||||
{
|
{
|
||||||
state.channel_control.bits = (state.channel_control.bits & ~ChannelState::ChannelControl::WRITE_MASK) |
|
state.channel_control.bits = (state.channel_control.bits & ~ChannelState::ChannelControl::WRITE_MASK) |
|
||||||
(value & ChannelState::ChannelControl::WRITE_MASK);
|
(value & ChannelState::ChannelControl::WRITE_MASK);
|
||||||
Log_DebugPrintf("DMA channel %u channel control <- 0x%08X", channel_index, state.channel_control.bits);
|
Log_TracePrintf("DMA channel %u channel control <- 0x%08X", channel_index, state.channel_control.bits);
|
||||||
if (CanRunChannel(static_cast<Channel>(channel_index)))
|
if (CanRunChannel(static_cast<Channel>(channel_index)))
|
||||||
UpdateTransferPending();
|
UpdateTransferPending();
|
||||||
|
|
||||||
|
@ -123,14 +123,14 @@ void DMA::WriteRegister(u32 offset, u32 value)
|
||||||
{
|
{
|
||||||
case 0x70:
|
case 0x70:
|
||||||
{
|
{
|
||||||
Log_DebugPrintf("DPCR <- 0x%08X", value);
|
Log_TracePrintf("DPCR <- 0x%08X", value);
|
||||||
m_DPCR.bits = value;
|
m_DPCR.bits = value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x74:
|
case 0x74:
|
||||||
{
|
{
|
||||||
Log_DebugPrintf("DCIR <- 0x%08X", value);
|
Log_TracePrintf("DCIR <- 0x%08X", value);
|
||||||
m_DICR.bits = (m_DICR.bits & ~DICR_WRITE_MASK) | (value & DICR_WRITE_MASK);
|
m_DICR.bits = (m_DICR.bits & ~DICR_WRITE_MASK) | (value & DICR_WRITE_MASK);
|
||||||
m_DICR.bits = (m_DICR.bits & ~DICR_RESET_MASK) & (value ^ DICR_RESET_MASK);
|
m_DICR.bits = (m_DICR.bits & ~DICR_RESET_MASK) & (value ^ DICR_RESET_MASK);
|
||||||
m_DICR.UpdateMasterFlag();
|
m_DICR.UpdateMasterFlag();
|
||||||
|
@ -214,7 +214,6 @@ void DMA::RunDMA(Channel channel)
|
||||||
{
|
{
|
||||||
ChannelState& cs = m_state[static_cast<u32>(channel)];
|
ChannelState& cs = m_state[static_cast<u32>(channel)];
|
||||||
const bool copy_to_device = cs.channel_control.copy_to_device;
|
const bool copy_to_device = cs.channel_control.copy_to_device;
|
||||||
Log_DebugPrintf("Running DMA for channel %u", static_cast<u32>(channel));
|
|
||||||
|
|
||||||
// start/trigger bit is cleared on beginning of transfer
|
// start/trigger bit is cleared on beginning of transfer
|
||||||
cs.channel_control.start_trigger = false;
|
cs.channel_control.start_trigger = false;
|
||||||
|
@ -226,7 +225,8 @@ void DMA::RunDMA(Channel channel)
|
||||||
case SyncMode::Manual:
|
case SyncMode::Manual:
|
||||||
{
|
{
|
||||||
const u32 word_count = cs.block_control.manual.GetWordCount();
|
const u32 word_count = cs.block_control.manual.GetWordCount();
|
||||||
Log_DebugPrintf(" ... copying %u words %s 0x%08X", word_count, copy_to_device ? "from" : "to", current_address);
|
Log_DebugPrintf("DMA%u: Copying %u words %s 0x%08X", static_cast<u32>(channel), word_count,
|
||||||
|
copy_to_device ? "from" : "to", current_address);
|
||||||
if (copy_to_device)
|
if (copy_to_device)
|
||||||
{
|
{
|
||||||
u32 words_remaining = word_count;
|
u32 words_remaining = word_count;
|
||||||
|
@ -265,6 +265,9 @@ void DMA::RunDMA(Channel channel)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Log_DebugPrintf("DMA%u: Copying linked list starting at 0x%08X to device", static_cast<u32>(channel),
|
||||||
|
current_address);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
u32 header;
|
u32 header;
|
||||||
|
@ -303,8 +306,8 @@ void DMA::RunDMA(Channel channel)
|
||||||
{
|
{
|
||||||
const u32 block_size = cs.block_control.request.GetBlockSize();
|
const u32 block_size = cs.block_control.request.GetBlockSize();
|
||||||
const u32 block_count = cs.block_control.request.GetBlockCount();
|
const u32 block_count = cs.block_control.request.GetBlockCount();
|
||||||
Log_DebugPrintf(" ... copying %u blocks of size %u %s 0x%08X", block_count, block_size,
|
Log_DebugPrintf("DMA%u: Copying %u blocks of size %u %s 0x%08X", static_cast<u32>(channel), block_count,
|
||||||
copy_to_device ? "from" : "to", current_address);
|
block_size, copy_to_device ? "from" : "to", current_address);
|
||||||
if (copy_to_device)
|
if (copy_to_device)
|
||||||
{
|
{
|
||||||
u32 words_remaining = block_size * block_count;
|
u32 words_remaining = block_size * block_count;
|
||||||
|
@ -344,12 +347,12 @@ void DMA::RunDMA(Channel channel)
|
||||||
cs.channel_control.enable_busy = false;
|
cs.channel_control.enable_busy = false;
|
||||||
if (m_DICR.IsIRQEnabled(channel))
|
if (m_DICR.IsIRQEnabled(channel))
|
||||||
{
|
{
|
||||||
Log_DebugPrintf("Set DMA interrupt for channel %u", static_cast<u32>(channel));
|
Log_TracePrintf("Set DMA interrupt for channel %u", static_cast<u32>(channel));
|
||||||
m_DICR.SetIRQFlag(channel);
|
m_DICR.SetIRQFlag(channel);
|
||||||
m_DICR.UpdateMasterFlag();
|
m_DICR.UpdateMasterFlag();
|
||||||
if (m_DICR.master_flag)
|
if (m_DICR.master_flag)
|
||||||
{
|
{
|
||||||
Log_DebugPrintf("Firing DMA interrupt");
|
Log_TracePrintf("Firing DMA interrupt");
|
||||||
m_interrupt_controller->InterruptRequest(InterruptController::IRQ::DMA);
|
m_interrupt_controller->InterruptRequest(InterruptController::IRQ::DMA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,8 +229,9 @@ void MDEC::HandleDecodeMacroblockCommand()
|
||||||
{
|
{
|
||||||
while (src != src_end)
|
while (src != src_end)
|
||||||
{
|
{
|
||||||
|
u32 old_offs = static_cast<u32>(src - temp.data());
|
||||||
src = DecodeColoredMacroblock(src, src_end);
|
src = DecodeColoredMacroblock(src, src_end);
|
||||||
Log_InfoPrint("Decoded colour macroblock");
|
Log_InfoPrintf("Decoded colour macroblock, ptr was %u, now %u", old_offs, static_cast<u32>(src - temp.data()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,7 +465,8 @@ void MDEC::IDCT(s16* blk)
|
||||||
for (u32 u = 0; u < 8; u++)
|
for (u32 u = 0; u < 8; u++)
|
||||||
sum += s64(temp_buffer[u + y * 8]) * s32(m_scale_table[u * 8 + x]);
|
sum += s64(temp_buffer[u + y * 8]) * s32(m_scale_table[u * 8 + x]);
|
||||||
|
|
||||||
blk[x + y * 8] = static_cast<s16>(std::clamp<s32>(SignExtendN<9, s32>((sum >> 32) + ((sum >> 31) & 1)), -128, 127));
|
blk[x + y * 8] =
|
||||||
|
static_cast<s16>(std::clamp<s32>(SignExtendN<9, s32>((sum >> 32) + ((sum >> 31) & 1)), -128, 127));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -494,7 +496,7 @@ void MDEC::yuv_to_rgb(u32 xx, u32 yy, const std::array<s16, 64>& Crblk, const st
|
||||||
|
|
||||||
rgb_out[(x + xx) + ((y + yy) * 16)] = ZeroExtend32(static_cast<u16>(R)) |
|
rgb_out[(x + xx) + ((y + yy) * 16)] = ZeroExtend32(static_cast<u16>(R)) |
|
||||||
(ZeroExtend32(static_cast<u16>(G)) << 8) |
|
(ZeroExtend32(static_cast<u16>(G)) << 8) |
|
||||||
(ZeroExtend32(static_cast<u16>(B)) << 16);
|
(ZeroExtend32(static_cast<u16>(B)) << 16) | UINT32_C(0xFF000000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue