Compare commits

...

5 Commits

Author SHA1 Message Date
Ty Lamontagne
c9642b70f6 CDVD: Only take ADR and track index/num from host IOCTL SUBQ
Fixes the OSDSYS CD player minute:second counter
2024-11-25 10:02:23 -05:00
Ty Lamontagne
849fa57bf6 CDVD: Adjust register logging 2024-11-25 10:02:23 -05:00
Ty Lamontagne
2c95ef76f1 CDVD: Minor cleanup and fix off-by-one TOC filling issue 2024-11-25 10:02:23 -05:00
Ty Lamontagne
4d9cb885b2 CDVD: Use disc track indexes for our track array. 2024-11-25 10:02:23 -05:00
Ty Lamontagne
e375f98f7a CDVD: Fix OSDSYS Audio CD regression.
There is still an existing issue with the tracks.
2024-11-25 10:02:23 -05:00
7 changed files with 74 additions and 65 deletions

View File

@@ -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;
}
}

View File

@@ -17,6 +17,7 @@
#include "common/ProgressCallback.h"
#include "common/StringUtil.h"
#include <array>
#include <ctype.h>
#include <exception>
#include <memory>
@@ -55,7 +56,7 @@ static OutputIsoFile blockDumpFile;
// Information about tracks on disc
u8 strack;
u8 etrack;
cdvdTrack tracks[100];
std::array<cdvdTrack, 100> 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.

View File

@@ -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<cdvdTrack, 100> tracks;
extern void CDVDsys_ChangeSource(CDVD_SourceType type);
extern void CDVDsys_SetFile(CDVD_SourceType srctype, std::string newfile);

View File

@@ -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())
{
@@ -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 >= tracks.size())
{
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<u8, 2352> 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
}
}
@@ -131,7 +133,7 @@ static void keepAliveThread()
std::unique_lock<std::mutex> 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");
@@ -271,20 +273,28 @@ static s32 DISCreadSubQ(u32 lsn, cdvdSubQ* subq)
memset(subq, 0, sizeof(cdvdSubQ));
lsn_to_msf(&subq->discM, &subq->discS, &subq->discF, lsn + 150);
u8 i = strack;
while (i < etrack && lsn >= tracks[i + 1].start_lba)
++i;
lsn -= tracks[i].start_lba;
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))
{
lsn_to_msf(&subq->discM, &subq->discS, &subq->discF, lsn + 150);
u8 i = strack;
while (i < etrack && lsn >= tracks[i + 1].start_lba)
++i;
lsn -= tracks[i].start_lba;
lsn_to_msf(&subq->trackM, &subq->trackS, &subq->trackF, lsn);
subq->adr = 1;
subq->ctrl = tracks[i].type;
subq->trackNum = i;
subq->trackIndex = 1;
}
@@ -470,11 +480,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);
}
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}