From c310413082b764fff7dee018ebe348187b9dfb95 Mon Sep 17 00:00:00 2001 From: Ty Lamontagne Date: Sun, 24 Nov 2024 13:33:19 -0500 Subject: [PATCH 1/5] CDVD: Fix OSDSYS Audio CD regression. There is still an existing issue with the tracks. --- pcsx2/SPU2/spu2sys.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pcsx2/SPU2/spu2sys.cpp b/pcsx2/SPU2/spu2sys.cpp index 78594e1be1eaf..359574abcfa97 100644 --- a/pcsx2/SPU2/spu2sys.cpp +++ b/pcsx2/SPU2/spu2sys.cpp @@ -420,10 +420,11 @@ __forceinline void UpdateSpdifMode() { const int OPM = PlayMode; - if (Spdif.Out & 0x4 && SPU2::MsgToConsole()) // use 24/32bit PCM data streaming + if (Spdif.Out & 0x4) // use 24/32bit PCM data streaming { PlayMode = 8; - SPU2::ConLog("* SPU2: WARNING: Possibly CDDA mode set!\n"); + if (SPU2::MsgToConsole()) + SPU2::ConLog("* SPU2: WARNING: Possibly CDDA mode set!\n"); return; } From dab6de85638eb5e48c9b755ece0f80ffb2d0ff84 Mon Sep 17 00:00:00 2001 From: Ty Lamontagne Date: Sun, 24 Nov 2024 14:16:38 -0500 Subject: [PATCH 2/5] CDVD: Use disc track indexes for our track array. --- pcsx2/CDVD/CDVDdiscReader.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/pcsx2/CDVD/CDVDdiscReader.cpp b/pcsx2/CDVD/CDVDdiscReader.cpp index f8f804201b6c6..10634b803b566 100644 --- a/pcsx2/CDVD/CDVDdiscReader.cpp +++ b/pcsx2/CDVD/CDVDdiscReader.cpp @@ -76,35 +76,37 @@ void cdvdParseTOC() strack = 0xFF; etrack = 0; - int i = 0; - for (auto& entry : src->ReadTOC()) { - if (entry.track < 1 || entry.track > 99) + const u8 track = entry.track; + if (track < 1 || track > 99) + { + Console.Warning("CDVD: Invalid track index %u, ignoring\n", track); continue; - strack = std::min(strack, entry.track); - etrack = std::max(etrack, entry.track); - tracks[i].start_lba = entry.lba; + } + strack = std::min(strack, track); + etrack = std::max(etrack, track); + tracks[track].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[i].type = CDVD_MODE2_TRACK; + tracks[track].type = CDVD_MODE2_TRACK; } else { - tracks[i].type = CDVD_MODE1_TRACK; + tracks[track].type = CDVD_MODE1_TRACK; } } else { - tracks[i].type = CDVD_AUDIO_TRACK; + tracks[track].type = CDVD_AUDIO_TRACK; } - fprintf(stderr, "Track %u start sector: %u\n", entry.track, entry.lba); - - i += 1; +#ifdef PCSX2_DEBUG + DevCon.Write("cdvdParseTOC: Track %u: LBA %u, Type %u\n", track, tracks[track].start_lba, tracks[track].type); +#endif } } From bb90f8df1e636b47d2839199f2d47dea2594508d Mon Sep 17 00:00:00 2001 From: Ty Lamontagne Date: Sun, 24 Nov 2024 15:02:47 -0500 Subject: [PATCH 3/5] CDVD: Minor cleanup and fix off-by-one TOC filling issue --- pcsx2/CDVD/CDVDcommon.cpp | 3 ++- pcsx2/CDVD/CDVDcommon.h | 24 ++++++++++++------------ pcsx2/CDVD/CDVDdiscReader.cpp | 16 +++++++++------- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/pcsx2/CDVD/CDVDcommon.cpp b/pcsx2/CDVD/CDVDcommon.cpp index 8e59ff1d7e453..5162b85440966 100644 --- a/pcsx2/CDVD/CDVDcommon.cpp +++ b/pcsx2/CDVD/CDVDcommon.cpp @@ -17,6 +17,7 @@ #include "common/ProgressCallback.h" #include "common/StringUtil.h" +#include #include #include #include @@ -55,7 +56,7 @@ static OutputIsoFile blockDumpFile; // Information about tracks on disc u8 strack; u8 etrack; -cdvdTrack tracks[100]; +std::array tracks; // Assertion check for CDVD != NULL (in devel and debug builds), because its handier than // relying on DEP exceptions -- and a little more reliable too. diff --git a/pcsx2/CDVD/CDVDcommon.h b/pcsx2/CDVD/CDVDcommon.h index fa6933007d150..4ac864d0fde19 100644 --- a/pcsx2/CDVD/CDVDcommon.h +++ b/pcsx2/CDVD/CDVDcommon.h @@ -10,7 +10,7 @@ class Error; class ProgressCallback; -typedef struct _cdvdTrackIndex +struct cdvdTrackIndex { bool isPregap; u8 trackM; // current minute offset from first track (BCD encoded) @@ -20,9 +20,9 @@ typedef struct _cdvdTrackIndex u8 discS; // current sector location on the disc (BCD encoded) u8 discF; // current frame location on the disc (BCD encoded) -} cdvdTrackIndex; +}; -typedef struct _cdvdTrack +struct cdvdTrack { u32 start_lba; // Starting lba of track, note that some formats will be missing 2 seconds, cue, bin u8 type; // Track Type @@ -36,10 +36,10 @@ typedef struct _cdvdTrack u8 discF; // current frame location on the disc (BCD encoded) // 0 is pregap, 1 is data - _cdvdTrackIndex index[2]; -} cdvdTrack; + cdvdTrackIndex index[2]; +}; -typedef struct _cdvdSubQ +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. @@ -52,19 +52,19 @@ typedef struct _cdvdSubQ 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 +struct cdvdTD { // NOT bcd coded u32 lsn; u8 type; -} cdvdTD; +}; -typedef struct _cdvdTN +struct cdvdTN { u8 strack; //number of the first track (usually 1) u8 etrack; //number of the last track -} cdvdTN; +}; // SpindleCtrl Masks #define CDVD_SPINDLE_SPEED 0x7 // Speed ranges from 0-3 (1, 2, 3, 4x for DVD) and 0-5 (1, 2, 4, 12, 24x for CD) @@ -185,7 +185,7 @@ extern const CDVD_API CDVDapi_NoDisc; extern u8 strack; extern u8 etrack; -extern cdvdTrack tracks[100]; +extern std::array tracks; extern void CDVDsys_ChangeSource(CDVD_SourceType type); extern void CDVDsys_SetFile(CDVD_SourceType srctype, std::string newfile); diff --git a/pcsx2/CDVD/CDVDdiscReader.cpp b/pcsx2/CDVD/CDVDdiscReader.cpp index 10634b803b566..75a4448c8cfb7 100644 --- a/pcsx2/CDVD/CDVDdiscReader.cpp +++ b/pcsx2/CDVD/CDVDdiscReader.cpp @@ -54,7 +54,7 @@ static void lsn_to_msf(u8* minute, u8* second, u8* frame, u32 lsn) // TocStuff void cdvdParseTOC() { - tracks[1].start_lba = 0; + tracks.fill(cdvdTrack{}); if (!src->GetSectorCount()) { @@ -79,7 +79,7 @@ void cdvdParseTOC() for (auto& entry : src->ReadTOC()) { const u8 track = entry.track; - if (track < 1 || track > 99) + if (track < 1 || track >= tracks.size()) { Console.Warning("CDVD: Invalid track index %u, ignoring\n", track); continue; @@ -472,11 +472,13 @@ static s32 DISCgetTOC(void* toc) { err = DISCgetTD(i, &trackInfo); lba_to_msf(trackInfo.lsn, &min, &sec, &frm); - tocBuff[i * 10 + 30] = trackInfo.type; - tocBuff[i * 10 + 32] = err == -1 ? 0 : dec_to_bcd(i); //number - tocBuff[i * 10 + 37] = dec_to_bcd(min); - tocBuff[i * 10 + 38] = dec_to_bcd(sec); - tocBuff[i * 10 + 39] = dec_to_bcd(frm); + + const u8 tocIndex = i - diskInfo.strack; + tocBuff[tocIndex * 10 + 30] = trackInfo.type; + tocBuff[tocIndex * 10 + 32] = err == -1 ? 0 : dec_to_bcd(i); //number + tocBuff[tocIndex * 10 + 37] = dec_to_bcd(min); + tocBuff[tocIndex * 10 + 38] = dec_to_bcd(sec); + tocBuff[tocIndex * 10 + 39] = dec_to_bcd(frm); fprintf(stderr, "Track %u: %u mins %u secs %u frames\n", i, min, sec, frm); } } From b4943cd508487e6f61132003e68593c9368f1b7a Mon Sep 17 00:00:00 2001 From: Ty Lamontagne Date: Sun, 24 Nov 2024 15:14:14 -0500 Subject: [PATCH 4/5] CDVD: Adjust register logging --- pcsx2/CDVD/CDVD.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/pcsx2/CDVD/CDVD.cpp b/pcsx2/CDVD/CDVD.cpp index c6aea29164d58..34bea0e58f07b 100644 --- a/pcsx2/CDVD/CDVD.cpp +++ b/pcsx2/CDVD/CDVD.cpp @@ -3013,6 +3013,20 @@ void cdvdWrite(u8 key, u8 rt) case 0x08: cdvdWrite08(rt); break; + case 0x09: + /* + The register 0xC, 0xD, 0xE give back MSF of the current sector being read/played from the actual DSP hardware. They are named "where" registers : where0, where1, where2. + They can be read anytime on hw as long as there is a valid disc and mode configured properly. Register 0x9 is where_select register which determines the mode for this registers. The mode must be set according to the used disc. + 0 = CDDA + 1 = CDROM + 2 = DVD + + If no disc or invalid mode for disc type then those registers return 0. Only official usage so far is cdvdman reading those registers and waiting to sync while doing SubQ. + Only logging writes different than 0 is enough. + */ + if (rt != 0) + Console.Warning("8bit write to addr 0x1f402009 = 0x%x", rt); + break; case 0x0A: cdvdWrite0A(rt); break; @@ -3035,7 +3049,7 @@ void cdvdWrite(u8 key, u8 rt) cdvdWrite3A(rt); break; default: - Console.Warning("IOP Unknown 8bit write to addr 0x1f4020%x = 0x%x", key, rt); + Console.Warning("IOP Unknown 8bit write to addr 0x1f4020%02x = 0x%x", key, rt); break; } } From 7cff6fc9a8541735143508199af9f0ff21416c89 Mon Sep 17 00:00:00 2001 From: Ty Lamontagne Date: Sun, 24 Nov 2024 18:26:58 -0500 Subject: [PATCH 5/5] CDVD: Only take ADR and track index/num from host IOCTL SUBQ Fixes the OSDSYS CD player minute:second counter --- pcsx2/CDVD/CDVDdiscReader.cpp | 30 +++++++++++++++++++----------- pcsx2/CDVD/Linux/IOCtlSrc.cpp | 10 ---------- pcsx2/CDVD/Windows/IOCtlSrc.cpp | 9 --------- 3 files changed, 19 insertions(+), 30 deletions(-) diff --git a/pcsx2/CDVD/CDVDdiscReader.cpp b/pcsx2/CDVD/CDVDdiscReader.cpp index 75a4448c8cfb7..6956bbbf9526c 100644 --- a/pcsx2/CDVD/CDVDdiscReader.cpp +++ b/pcsx2/CDVD/CDVDdiscReader.cpp @@ -105,7 +105,7 @@ void cdvdParseTOC() tracks[track].type = CDVD_AUDIO_TRACK; } #ifdef PCSX2_DEBUG - DevCon.Write("cdvdParseTOC: Track %u: LBA %u, Type %u\n", track, tracks[track].start_lba, tracks[track].type); + DevCon.Write("cdvdParseTOC: Track %u: LBA %u, Type %u\n", track, tracks[track].start_lba, tracks[track].type); #endif } } @@ -133,7 +133,7 @@ static void keepAliveThread() std::unique_lock guard(s_keepalive_lock); while (!s_keepalive_cv.wait_for(guard, std::chrono::seconds(30), - []() { return !s_keepalive_is_open; })) + []() { return !s_keepalive_is_open; })) { //printf(" * keepAliveThread: polling drive.\n"); @@ -273,20 +273,28 @@ static s32 DISCreadSubQ(u32 lsn, cdvdSubQ* subq) memset(subq, 0, sizeof(cdvdSubQ)); - if (!src->ReadTrackSubQ(subq)) - { - lsn_to_msf(&subq->discM, &subq->discS, &subq->discF, lsn + 150); + 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->ctrl = tracks[i].type; + // It's important to note that we do _not_ use the current MSF values + // from the host's device. We use the MSF values from the lsn. + // An easy way to test an implementation is to see if the OSDSYS + // CD player can display the correct minute and second values. + // From my testing, the IOCTL returns 0 for ctrl. This also breaks + // the OSDSYS player. The only "safe" values to receive from the IOCTL + // are ADR, trackNum and trackIndex. + if (!src->ReadTrackSubQ(subq)) + { subq->adr = 1; - subq->ctrl = tracks[i].type; subq->trackNum = i; subq->trackIndex = 1; } diff --git a/pcsx2/CDVD/Linux/IOCtlSrc.cpp b/pcsx2/CDVD/Linux/IOCtlSrc.cpp index cb79222446c2c..c180d7585a76d 100644 --- a/pcsx2/CDVD/Linux/IOCtlSrc.cpp +++ b/pcsx2/CDVD/Linux/IOCtlSrc.cpp @@ -208,18 +208,8 @@ bool IOCtlSrc::ReadTrackSubQ(cdvdSubQ* subQ) const } 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; } diff --git a/pcsx2/CDVD/Windows/IOCtlSrc.cpp b/pcsx2/CDVD/Windows/IOCtlSrc.cpp index f6e004be5f68c..005f6e846a528 100644 --- a/pcsx2/CDVD/Windows/IOCtlSrc.cpp +++ b/pcsx2/CDVD/Windows/IOCtlSrc.cpp @@ -320,17 +320,8 @@ bool IOCtlSrc::ReadTrackSubQ(cdvdSubQ* subQ) const 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;