From 40dceacc7c3c2f750081e9b4b9517d811624bed5 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Mon, 30 Sep 2019 20:01:41 +1000 Subject: [PATCH] CDROM: Detection of XA audio sectors --- src/pse/cdrom.cpp | 85 ++++++++++++++++++++++++++++++++++------------- src/pse/cdrom.h | 38 ++++++++++++++++++++- src/pse/dma.cpp | 25 ++++++++------ src/pse/mdec.cpp | 8 +++-- 4 files changed, 118 insertions(+), 38 deletions(-) diff --git a/src/pse/cdrom.cpp b/src/pse/cdrom.cpp index d42636de2..78858a4bc 100644 --- a/src/pse/cdrom.cpp +++ b/src/pse/cdrom.cpp @@ -123,7 +123,7 @@ u8 CDROM::ReadRegister(u32 offset) switch (offset) { 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; case 1: // always response FIFO @@ -184,7 +184,7 @@ void CDROM::WriteRegister(u32 offset, u8 value) { 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(~3)) | (value & u8(3)); return; } @@ -277,16 +277,7 @@ void CDROM::WriteRegister(u32 offset, u8 value) Assert(!rr.SMEN); if (rr.BFRD) { - // any data to load? - 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(m_sector_buffer.size())); - m_sector_buffer.clear(); + LoadDataFIFO(); } else { @@ -361,7 +352,7 @@ u32 CDROM::DMARead() 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; } @@ -755,19 +746,44 @@ void CDROM::DoSectorRead() // return; } - Log_DevPrintf("Reading sector %llu", m_media->GetCurrentLBA()); - // TODO: Error handling // TODO: Sector buffer should be two sectors? Assert(!m_mode.ignore_bit); - const u32 size = - m_mode.read_raw_sector ? (CDImage::RAW_SECTOR_SIZE - CDImage::SECTOR_SYNC_SIZE) : CDImage::DATA_SECTOR_SIZE; - m_sector_buffer.resize(size); - m_media->Read(m_mode.read_raw_sector ? CDImage::ReadMode::RawNoSync : CDImage::ReadMode::DataOnly, 1, - m_sector_buffer.data()); - m_response_fifo.Push(m_secondary_status.bits); - SetInterrupt(Interrupt::INT1); - UpdateStatusRegister(); + m_sector_buffer.resize(CDImage::RAW_SECTOR_SIZE); + m_media->Read(CDImage::ReadMode::RawSector, 1, m_sector_buffer.data()); + Log_DevPrintf("Read sector %llu: mode %u submode 0x%02X", m_media->GetCurrentLBA(), ZeroExtend32(m_sector_buffer[15]), + ZeroExtend32(m_sector_buffer[18])); + + bool pass_to_cpu = true; + if (m_mode.xa_enable) + { + const CDSectorHeader* sh = + reinterpret_cast(m_sector_buffer.data() + CDImage::SECTOR_SYNC_SIZE); + if (sh->sector_mode == 2) + { + const XASubHeader* xsh = reinterpret_cast(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); + SetInterrupt(Interrupt::INT1); + UpdateStatusRegister(); + } m_sector_read_remaining_ticks += GetTicksForRead(); m_system->SetDowncount(m_sector_read_remaining_ticks); @@ -782,3 +798,26 @@ void CDROM::StopReading() m_secondary_status.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(); +} diff --git a/src/pse/cdrom.h b/src/pse/cdrom.h index cc621c294..fad5ab651 100644 --- a/src/pse/cdrom.h +++ b/src/pse/cdrom.h @@ -134,7 +134,7 @@ private: BitField xa_filter; BitField ignore_bit; BitField read_raw_sector; - BitField xa_adpcm; + BitField xa_enable; BitField double_speed; }; @@ -146,6 +146,41 @@ private: BitField 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 eor; + BitField video; + BitField audio; + BitField data; + BitField trigger; + BitField form2; + BitField realtime; + BitField eof; + } submode; + union Codinginfo + { + u8 bits; + + BitField mono_stereo; + BitField sample_rate; + BitField bits_per_sample; + BitField emphasis; + } codinginfo; + }; + bool HasPendingInterrupt() const { return m_interrupt_flag_register != 0; } void SetInterrupt(Interrupt interrupt); void PushStatResponse(Interrupt interrupt = Interrupt::ACK); @@ -161,6 +196,7 @@ private: void BeginReading(); void DoSectorRead(); void StopReading(); + void LoadDataFIFO(); System* m_system = nullptr; DMA* m_dma = nullptr; diff --git a/src/pse/dma.cpp b/src/pse/dma.cpp index 592fd5f29..ea6d2eb08 100644 --- a/src/pse/dma.cpp +++ b/src/pse/dma.cpp @@ -92,12 +92,12 @@ void DMA::WriteRegister(u32 offset, u32 value) case 0x00: { 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; } 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; return; } @@ -106,7 +106,7 @@ void DMA::WriteRegister(u32 offset, u32 value) { state.channel_control.bits = (state.channel_control.bits & ~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_index))) UpdateTransferPending(); @@ -123,14 +123,14 @@ void DMA::WriteRegister(u32 offset, u32 value) { case 0x70: { - Log_DebugPrintf("DPCR <- 0x%08X", value); + Log_TracePrintf("DPCR <- 0x%08X", value); m_DPCR.bits = value; return; } 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_RESET_MASK) & (value ^ DICR_RESET_MASK); m_DICR.UpdateMasterFlag(); @@ -214,7 +214,6 @@ void DMA::RunDMA(Channel channel) { ChannelState& cs = m_state[static_cast(channel)]; const bool copy_to_device = cs.channel_control.copy_to_device; - Log_DebugPrintf("Running DMA for channel %u", static_cast(channel)); // start/trigger bit is cleared on beginning of transfer cs.channel_control.start_trigger = false; @@ -226,7 +225,8 @@ void DMA::RunDMA(Channel channel) case SyncMode::Manual: { 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(channel), word_count, + copy_to_device ? "from" : "to", current_address); if (copy_to_device) { u32 words_remaining = word_count; @@ -265,6 +265,9 @@ void DMA::RunDMA(Channel channel) } else { + Log_DebugPrintf("DMA%u: Copying linked list starting at 0x%08X to device", static_cast(channel), + current_address); + for (;;) { u32 header; @@ -303,8 +306,8 @@ void DMA::RunDMA(Channel channel) { const u32 block_size = cs.block_control.request.GetBlockSize(); const u32 block_count = cs.block_control.request.GetBlockCount(); - Log_DebugPrintf(" ... copying %u blocks of size %u %s 0x%08X", block_count, block_size, - copy_to_device ? "from" : "to", current_address); + Log_DebugPrintf("DMA%u: Copying %u blocks of size %u %s 0x%08X", static_cast(channel), block_count, + block_size, copy_to_device ? "from" : "to", current_address); if (copy_to_device) { u32 words_remaining = block_size * block_count; @@ -344,12 +347,12 @@ void DMA::RunDMA(Channel channel) cs.channel_control.enable_busy = false; if (m_DICR.IsIRQEnabled(channel)) { - Log_DebugPrintf("Set DMA interrupt for channel %u", static_cast(channel)); + Log_TracePrintf("Set DMA interrupt for channel %u", static_cast(channel)); m_DICR.SetIRQFlag(channel); m_DICR.UpdateMasterFlag(); if (m_DICR.master_flag) { - Log_DebugPrintf("Firing DMA interrupt"); + Log_TracePrintf("Firing DMA interrupt"); m_interrupt_controller->InterruptRequest(InterruptController::IRQ::DMA); } } diff --git a/src/pse/mdec.cpp b/src/pse/mdec.cpp index 6066ec93a..4b8b10057 100644 --- a/src/pse/mdec.cpp +++ b/src/pse/mdec.cpp @@ -229,8 +229,9 @@ void MDEC::HandleDecodeMacroblockCommand() { while (src != src_end) { + u32 old_offs = static_cast(src - temp.data()); src = DecodeColoredMacroblock(src, src_end); - Log_InfoPrint("Decoded colour macroblock"); + Log_InfoPrintf("Decoded colour macroblock, ptr was %u, now %u", old_offs, static_cast(src - temp.data())); } } } @@ -464,7 +465,8 @@ void MDEC::IDCT(s16* blk) for (u32 u = 0; u < 8; u++) sum += s64(temp_buffer[u + y * 8]) * s32(m_scale_table[u * 8 + x]); - blk[x + y * 8] = static_cast(std::clamp(SignExtendN<9, s32>((sum >> 32) + ((sum >> 31) & 1)), -128, 127)); + blk[x + y * 8] = + static_cast(std::clamp(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& Crblk, const st rgb_out[(x + xx) + ((y + yy) * 16)] = ZeroExtend32(static_cast(R)) | (ZeroExtend32(static_cast(G)) << 8) | - (ZeroExtend32(static_cast(B)) << 16); + (ZeroExtend32(static_cast(B)) << 16) | UINT32_C(0xFF000000); } } }