From 0b46a8cfc40c86590c845cf1511c458aa4d7c92c Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Fri, 4 Oct 2019 19:05:19 +1000 Subject: [PATCH] CDROM: Implement GetlocP/GetlocL commands --- src/common/cd_image.h | 44 +++++++++++++++++++++++++++--- src/core/cdrom.cpp | 63 +++++++++++++++++++++++++++++-------------- src/core/cdrom.h | 53 ++++++++++-------------------------- 3 files changed, 98 insertions(+), 62 deletions(-) diff --git a/src/common/cd_image.h b/src/common/cd_image.h index f27c78f51..8b3f6e1a8 100644 --- a/src/common/cd_image.h +++ b/src/common/cd_image.h @@ -1,4 +1,5 @@ #pragma once +#include "bitfield.h" #include "types.h" class ByteStream; @@ -14,6 +15,8 @@ public: RAW_SECTOR_SIZE = 2352, DATA_SECTOR_SIZE = 2048, SECTOR_SYNC_SIZE = 12, + SECTOR_HEADER_SIZE = 4, + SECTOR_XA_SUBHEADER_SIZE = 4, FRAMES_PER_SECOND = 75, // "sectors" SECONDS_PER_MINUTE = 60, FRAMES_PER_MINUTE = FRAMES_PER_SECOND * SECONDS_PER_MINUTE, @@ -21,9 +24,44 @@ public: enum class ReadMode : u32 { - DataOnly, // 2048 bytes per sector. - RawSector, // 2352 bytes per sector. - RawNoSync, // 2340 bytes per sector. + DataOnly, // 2048 bytes per sector. + RawSector, // 2352 bytes per sector. + RawNoSync, // 2340 bytes per sector. + }; + + struct SectorHeader + { + 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; }; // Conversion helpers. diff --git a/src/core/cdrom.cpp b/src/core/cdrom.cpp index 78858a4bc..df23476c8 100644 --- a/src/core/cdrom.cpp +++ b/src/core/cdrom.cpp @@ -683,6 +683,33 @@ void CDROM::ExecuteCommand() } break; + case Command::GetlocL: + { + Log_DebugPrintf("CDROM GetlocL command"); + m_response_fifo.PushRange(reinterpret_cast(&m_last_sector_header), sizeof(m_last_sector_header)); + m_response_fifo.PushRange(reinterpret_cast(&m_last_sector_subheader), sizeof(m_last_sector_subheader)); + SetInterrupt(Interrupt::ACK); + EndCommand(); + } + break; + + case Command::GetlocP: + { + // TODO: Subchannel Q support.. + Log_DebugPrintf("CDROM GetlocP command"); + m_response_fifo.Push(1); // track number + m_response_fifo.Push(1); // index + m_response_fifo.Push(DecimalToBCD(m_last_sector_header.minute)); // minute within track + m_response_fifo.Push(DecimalToBCD(m_last_sector_header.second)); // second within track + m_response_fifo.Push(DecimalToBCD(m_last_sector_header.frame)); // frame within track + m_response_fifo.Push(DecimalToBCD(m_last_sector_header.minute)); // minute on entire disc + m_response_fifo.Push(DecimalToBCD(m_last_sector_header.second)); // second on entire disc + m_response_fifo.Push(DecimalToBCD(m_last_sector_header.frame)); // frame on entire disc + SetInterrupt(Interrupt::ACK); + EndCommand(); + } + break; + default: Panic("Unknown command"); break; @@ -749,32 +776,28 @@ void CDROM::DoSectorRead() // TODO: Error handling // TODO: Sector buffer should be two sectors? Assert(!m_mode.ignore_bit); - m_sector_buffer.resize(CDImage::RAW_SECTOR_SIZE); + m_sector_buffer.resize(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])); + std::memcpy(&m_last_sector_header, &m_sector_buffer[SECTOR_SYNC_SIZE], sizeof(m_last_sector_header)); + std::memcpy(&m_last_sector_subheader, &m_sector_buffer[SECTOR_SYNC_SIZE + sizeof(m_last_sector_header)], + sizeof(m_last_sector_subheader)); + Log_DevPrintf("Read sector %llu: mode %u submode 0x%02X", m_media->GetCurrentLBA(), + ZeroExtend32(m_last_sector_header.sector_mode), ZeroExtend32(m_last_sector_subheader.submode.bits)); bool pass_to_cpu = true; - if (m_mode.xa_enable) + if (m_mode.xa_enable && m_last_sector_header.sector_mode == 2) { - const CDSectorHeader* sh = - reinterpret_cast(m_sector_buffer.data() + CDImage::SECTOR_SYNC_SIZE); - if (sh->sector_mode == 2) + if (m_last_sector_subheader.submode.realtime && m_last_sector_subheader.submode.audio) { - 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; - } + // 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 (m_last_sector_subheader.submode.eof) + { + Log_WarningPrintf("End of CD-XA file"); } } diff --git a/src/core/cdrom.h b/src/core/cdrom.h index fad5ab651..6bd91652e 100644 --- a/src/core/cdrom.h +++ b/src/core/cdrom.h @@ -1,11 +1,11 @@ #pragma once #include "common/bitfield.h" #include "common/fifo_queue.h" +#include "common/cd_image.h" #include "types.h" #include #include -class CDImage; class StateWrapper; class System; @@ -34,6 +34,14 @@ public: void Execute(TickCount ticks); private: + enum : u32 + { + RAW_SECTOR_SIZE = CDImage::RAW_SECTOR_SIZE, + SECTOR_SYNC_SIZE = CDImage::SECTOR_SYNC_SIZE, + SECTOR_HEADER_SIZE = CDImage::SECTOR_HEADER_SIZE, + SECTOR_XA_SUBHEADER_SIZE = CDImage::SECTOR_XA_SUBHEADER_SIZE, + }; + static constexpr u32 PARAM_FIFO_SIZE = 16; static constexpr u32 RESPONSE_FIFO_SIZE = 16; static constexpr u32 DATA_FIFO_SIZE = 4096; @@ -146,41 +154,6 @@ 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); @@ -213,13 +186,15 @@ private: bool m_reading = false; bool m_muted = false; - Loc m_setloc = {}; - bool m_setloc_dirty = false; - StatusRegister m_status = {}; SecondaryStatusRegister m_secondary_status = {}; ModeRegister m_mode = {}; + Loc m_setloc = {}; + bool m_setloc_dirty = false; + CDImage::SectorHeader m_last_sector_header = {}; + CDImage::XASubHeader m_last_sector_subheader = {}; + u8 m_interrupt_enable_register = INTERRUPT_REGISTER_MASK; u8 m_interrupt_flag_register = 0;