From fae15404d907f8f9d71c4059521a8a031efcc9e9 Mon Sep 17 00:00:00 2001 From: weirdbeardgame Date: Sun, 8 Sep 2024 17:12:29 -0700 Subject: [PATCH 1/2] CDVD: Added cdvdTrack, cdvdTrackIndex used IOCtl SubQ reads to get proper control register Added Checks for Control fields. --- pcsx2/CDVD/CDVDcommon.cpp | 5 +++ pcsx2/CDVD/CDVDcommon.h | 57 +++++++++++++++++++++++++++------ pcsx2/CDVD/CDVDdiscReader.cpp | 28 ++++++++-------- pcsx2/CDVD/CDVDdiscReader.h | 12 ++----- pcsx2/CDVD/CDVDisoReader.cpp | 2 +- pcsx2/CDVD/Darwin/IOCtlSrc.cpp | 5 +++ pcsx2/CDVD/Linux/IOCtlSrc.cpp | 30 +++++++++++++++++ pcsx2/CDVD/Windows/IOCtlSrc.cpp | 33 +++++++++++++++++++ 8 files changed, 138 insertions(+), 34 deletions(-) diff --git a/pcsx2/CDVD/CDVDcommon.cpp b/pcsx2/CDVD/CDVDcommon.cpp index d8a011f273..8e59ff1d7e 100644 --- a/pcsx2/CDVD/CDVDcommon.cpp +++ b/pcsx2/CDVD/CDVDcommon.cpp @@ -52,6 +52,11 @@ u32 lastLSN; // needed for block dumping static OutputIsoFile blockDumpFile; +// Information about tracks on disc +u8 strack; +u8 etrack; +cdvdTrack tracks[100]; + // Assertion check for CDVD != NULL (in devel and debug builds), because its handier than // relying on DEP exceptions -- and a little more reliable too. static void CheckNullCDVD() diff --git a/pcsx2/CDVD/CDVDcommon.h b/pcsx2/CDVD/CDVDcommon.h index f1e0efbc8f..fa6933007d 100644 --- a/pcsx2/CDVD/CDVDcommon.h +++ b/pcsx2/CDVD/CDVDcommon.h @@ -10,19 +10,48 @@ class Error; class ProgressCallback; -typedef struct _cdvdSubQ +typedef struct _cdvdTrackIndex { - u8 ctrl : 4; // control and mode bits - u8 mode : 4; // control and mode bits + bool isPregap; + u8 trackM; // current minute offset from first track (BCD encoded) + u8 trackS; // current sector offset from first track (BCD encoded) + u8 trackF; // current frame offset from first track (BCD encoded) + u8 discM; // current minute location on the disc (BCD encoded) + u8 discS; // current sector location on the disc (BCD encoded) + u8 discF; // current frame location on the disc (BCD encoded) + +} cdvdTrackIndex; + +typedef struct _cdvdTrack +{ + u32 start_lba; // Starting lba of track, note that some formats will be missing 2 seconds, cue, bin + u8 type; // Track Type u8 trackNum; // current track number (1 to 99) u8 trackIndex; // current index within track (0 to 99) - u8 trackM; // current minute location on the disc (BCD encoded) - u8 trackS; // current sector location on the disc (BCD encoded) - u8 trackF; // current frame location on the disc (BCD encoded) + u8 trackM; // current minute offset from first track (BCD encoded) + u8 trackS; // current sector offset from first track (BCD encoded) + u8 trackF; // current frame offset from first track (BCD encoded) + u8 discM; // current minute location on the disc (BCD encoded) + u8 discS; // current sector location on the disc (BCD encoded) + u8 discF; // current frame location on the disc (BCD encoded) + + // 0 is pregap, 1 is data + _cdvdTrackIndex index[2]; +} cdvdTrack; + +typedef struct _cdvdSubQ +{ + u8 ctrl : 4; // control and adr bits + u8 adr : 4; // control and adr bits, note that adr determines what SubQ info we're recieving. + u8 trackNum; // current track number (1 to 99) + u8 trackIndex; // current index within track (0 to 99) + u8 trackM; // current minute offset from first track (BCD encoded) + u8 trackS; // current sector offset from first track (BCD encoded) + u8 trackF; // current frame offset from first track (BCD encoded) u8 pad; // unused - u8 discM; // current minute offset from first track (BCD encoded) - u8 discS; // current sector offset from first track (BCD encoded) - u8 discF; // current frame offset from first track (BCD encoded) + u8 discM; // current minute location on the disc (BCD encoded) + u8 discS; // current sector location on the disc (BCD encoded) + u8 discF; // current frame location on the disc (BCD encoded) } cdvdSubQ; typedef struct _cdvdTD @@ -65,6 +94,12 @@ typedef struct _cdvdTN #define CDVD_TYPE_DETCT 0x01 // Detecting #define CDVD_TYPE_NODISC 0x00 // No Disc +// SUBQ CONTROL: +#define CDVD_CONTROL_AUDIO_PREEMPHASIS(control) ((control & (4 << 1))) +#define CDVD_CONTROL_DIGITAL_COPY_ALLOWED(control) ((control & (5 << 1))) +#define CDVD_CONTROL_IS_DATA(control) ((control & (6 << 1))) // Detects if track is Data or Audio +#define CDVD_CONTROL_IS_QUADRAPHONIC_AUDIO(control) ((control & (7 << 1))) + // CDVDgetTrayStatus returns: #define CDVD_TRAY_CLOSE 0x00 #define CDVD_TRAY_OPEN 0x01 @@ -148,6 +183,10 @@ extern const CDVD_API CDVDapi_Iso; extern const CDVD_API CDVDapi_Disc; extern const CDVD_API CDVDapi_NoDisc; +extern u8 strack; +extern u8 etrack; +extern cdvdTrack tracks[100]; + extern void CDVDsys_ChangeSource(CDVD_SourceType type); extern void CDVDsys_SetFile(CDVD_SourceType srctype, std::string newfile); extern const std::string& CDVDsys_GetFile(CDVD_SourceType srctype); diff --git a/pcsx2/CDVD/CDVDdiscReader.cpp b/pcsx2/CDVD/CDVDdiscReader.cpp index 02eccc5eed..89ba329a4d 100644 --- a/pcsx2/CDVD/CDVDdiscReader.cpp +++ b/pcsx2/CDVD/CDVDdiscReader.cpp @@ -4,6 +4,7 @@ #include "CDVDdiscReader.h" #include "CDVD/CDVD.h" #include "Host.h" +#include "common/Console.h" #include "common/Error.h" @@ -23,10 +24,6 @@ static std::thread s_keepalive_thread; /////////////////////////////////////////////////////////////////////////////// // State Information // -u8 strack; -u8 etrack; -track tracks[100]; - int curDiskType; int curTrayStatus; @@ -270,20 +267,23 @@ static s32 DISCreadSubQ(u32 lsn, cdvdSubQ* subq) memset(subq, 0, sizeof(cdvdSubQ)); - lsn_to_msf(&subq->discM, &subq->discS, &subq->discF, lsn + 150); + if (!src->ReadTrackSubQ(subq)) + { + lsn_to_msf(&subq->discM, &subq->discS, &subq->discF, lsn + 150); - u8 i = strack; - while (i < etrack && lsn >= tracks[i + 1].start_lba) - ++i; + u8 i = strack; + while (i < etrack && lsn >= tracks[i + 1].start_lba) + ++i; - lsn -= tracks[i].start_lba; + lsn -= tracks[i].start_lba; - lsn_to_msf(&subq->trackM, &subq->trackS, &subq->trackF, lsn); + lsn_to_msf(&subq->trackM, &subq->trackS, &subq->trackF, lsn); - subq->mode = 1; - subq->ctrl = tracks[i].type; - subq->trackNum = i; - subq->trackIndex = 1; + subq->adr = 1; + subq->ctrl = tracks[i].type; + subq->trackNum = i; + subq->trackIndex = 1; + } return 0; } diff --git a/pcsx2/CDVD/CDVDdiscReader.h b/pcsx2/CDVD/CDVDdiscReader.h index 38e23ad492..9b71735716 100644 --- a/pcsx2/CDVD/CDVDdiscReader.h +++ b/pcsx2/CDVD/CDVDdiscReader.h @@ -7,6 +7,7 @@ #include "common/RedtapeWindows.h" #endif +#include "CDVDcommon.h" #include "common/Pcsx2Defs.h" #include @@ -17,16 +18,6 @@ class Error; -struct track -{ - u32 start_lba; - u8 type; -}; - -extern u8 strack; -extern u8 etrack; -extern track tracks[100]; - extern int curDiskType; extern int curTrayStatus; @@ -70,6 +61,7 @@ public: const std::vector& ReadTOC() const; bool ReadSectors2048(u32 sector, u32 count, u8* buffer) const; bool ReadSectors2352(u32 sector, u32 count, u8* buffer) const; + bool ReadTrackSubQ(cdvdSubQ* subq) const; u32 GetLayerBreakAddress() const; s32 GetMediaType() const; void SetSpindleSpeed(bool restore_defaults) const; diff --git a/pcsx2/CDVD/CDVDisoReader.cpp b/pcsx2/CDVD/CDVDisoReader.cpp index 43a6473327..f15064f5b5 100644 --- a/pcsx2/CDVD/CDVDisoReader.cpp +++ b/pcsx2/CDVD/CDVDisoReader.cpp @@ -65,7 +65,7 @@ static s32 ISOreadSubQ(u32 lsn, cdvdSubQ* subq) // fake it u8 min, sec, frm; subq->ctrl = 4; - subq->mode = 1; + subq->adr = 1; subq->trackNum = itob(1); subq->trackIndex = itob(1); diff --git a/pcsx2/CDVD/Darwin/IOCtlSrc.cpp b/pcsx2/CDVD/Darwin/IOCtlSrc.cpp index 86f66c5990..9fce3a72de 100644 --- a/pcsx2/CDVD/Darwin/IOCtlSrc.cpp +++ b/pcsx2/CDVD/Darwin/IOCtlSrc.cpp @@ -241,6 +241,11 @@ bool IOCtlSrc::ReadCDInfo() #endif } +bool IOCtlSrc::ReadTrackSubQ(cdvdSubQ* subQ) const +{ + return false; +} + bool IOCtlSrc::DiscReady() { #ifdef __APPLE__ diff --git a/pcsx2/CDVD/Linux/IOCtlSrc.cpp b/pcsx2/CDVD/Linux/IOCtlSrc.cpp index fced12ee89..cb79222446 100644 --- a/pcsx2/CDVD/Linux/IOCtlSrc.cpp +++ b/pcsx2/CDVD/Linux/IOCtlSrc.cpp @@ -5,6 +5,7 @@ #include "CDVD/CDVD.h" #include "common/Error.h" +#include "common/Console.h" #include #include @@ -194,6 +195,35 @@ bool IOCtlSrc::ReadCDInfo() return true; } +bool IOCtlSrc::ReadTrackSubQ(cdvdSubQ* subQ) const +{ + cdrom_subchnl osSubQ; + + osSubQ.cdsc_format = CDROM_MSF; + + if (ioctl(m_device, CDROMSUBCHNL, &osSubQ) == -1) + { + Console.Error("SUB CHANNEL READ ERROR: %s\n", strerror(errno)); + return false; + } + + subQ->adr = osSubQ.cdsc_adr; + subQ->ctrl = osSubQ.cdsc_ctrl; + subQ->trackNum = osSubQ.cdsc_trk; + subQ->trackIndex = osSubQ.cdsc_ind; + + subQ->discM = osSubQ.cdsc_absaddr.msf.minute; + subQ->discS = osSubQ.cdsc_absaddr.msf.second; + subQ->discF = osSubQ.cdsc_absaddr.msf.frame; + + subQ->trackM = osSubQ.cdsc_reladdr.msf.minute; + subQ->trackS = osSubQ.cdsc_reladdr.msf.second; + subQ->trackF = osSubQ.cdsc_reladdr.msf.frame; + + return true; +} + + bool IOCtlSrc::DiscReady() { if (m_device == -1) diff --git a/pcsx2/CDVD/Windows/IOCtlSrc.cpp b/pcsx2/CDVD/Windows/IOCtlSrc.cpp index 3188a5d98c..f6e004be5f 100644 --- a/pcsx2/CDVD/Windows/IOCtlSrc.cpp +++ b/pcsx2/CDVD/Windows/IOCtlSrc.cpp @@ -10,6 +10,7 @@ #include #include #include +#include // "typedef ignored" warning will disappear once we move to the Windows 10 SDK. #pragma warning(push) #pragma warning(disable : 4091) @@ -303,6 +304,38 @@ bool IOCtlSrc::ReadCDInfo() return true; } +bool IOCtlSrc::ReadTrackSubQ(cdvdSubQ* subQ) const +{ + CDROM_SUB_Q_DATA_FORMAT format; + SUB_Q_CHANNEL_DATA osSubQ{}; + DWORD unused; + + format.Format = IOCTL_CDROM_CURRENT_POSITION; + + if (!DeviceIoControl(m_device, IOCTL_CDROM_READ_Q_CHANNEL, &format, sizeof(format), &osSubQ, sizeof(osSubQ), &unused, nullptr)) + { + Console.Error("SUB CHANNEL READ ERROR: %d\n", errno); + return false; + } + else + { + subQ->adr = osSubQ.CurrentPosition.ADR; + subQ->ctrl = osSubQ.CurrentPosition.Control; + subQ->trackNum = osSubQ.CurrentPosition.TrackNumber; + subQ->trackIndex = osSubQ.CurrentPosition.IndexNumber; + + subQ->trackM = osSubQ.CurrentPosition.TrackRelativeAddress[0]; + subQ->trackS = osSubQ.CurrentPosition.TrackRelativeAddress[1]; + subQ->trackF = osSubQ.CurrentPosition.TrackRelativeAddress[2]; + + subQ->discM = osSubQ.CurrentPosition.AbsoluteAddress[0]; + subQ->discS = osSubQ.CurrentPosition.AbsoluteAddress[1]; + subQ->discF = osSubQ.CurrentPosition.AbsoluteAddress[2]; + } + + return true; +} + bool IOCtlSrc::DiscReady() { if (m_device == INVALID_HANDLE_VALUE) From 759ffa6d6c2aeb7a18f32a1e5c8e2f078686430a Mon Sep 17 00:00:00 2001 From: weirdbeardgame Date: Sun, 15 Sep 2024 16:14:48 -0700 Subject: [PATCH 2/2] CDVD: 0 index into tracks array --- pcsx2/CDVD/CDVDdiscReader.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pcsx2/CDVD/CDVDdiscReader.cpp b/pcsx2/CDVD/CDVDdiscReader.cpp index 89ba329a4d..f8f804201b 100644 --- a/pcsx2/CDVD/CDVDdiscReader.cpp +++ b/pcsx2/CDVD/CDVDdiscReader.cpp @@ -76,31 +76,35 @@ void cdvdParseTOC() strack = 0xFF; etrack = 0; + int i = 0; + for (auto& entry : src->ReadTOC()) { if (entry.track < 1 || entry.track > 99) continue; strack = std::min(strack, entry.track); etrack = std::max(etrack, entry.track); - tracks[entry.track].start_lba = entry.lba; + tracks[i].start_lba = entry.lba; if ((entry.control & 0x0C) == 0x04) { std::array buffer; // Byte 15 of a raw CD data sector determines the track mode if (src->ReadSectors2352(entry.lba, 1, buffer.data()) && (buffer[15] & 3) == 2) { - tracks[entry.track].type = CDVD_MODE2_TRACK; + tracks[i].type = CDVD_MODE2_TRACK; } else { - tracks[entry.track].type = CDVD_MODE1_TRACK; + tracks[i].type = CDVD_MODE1_TRACK; } } else { - tracks[entry.track].type = CDVD_AUDIO_TRACK; + tracks[i].type = CDVD_AUDIO_TRACK; } fprintf(stderr, "Track %u start sector: %u\n", entry.track, entry.lba); + + i += 1; } }