From 02dfc5d20dac9a139151bc47d7e922cfad60b143 Mon Sep 17 00:00:00 2001 From: kenshen112 Date: Mon, 7 Mar 2022 11:12:01 -0700 Subject: [PATCH] cdrom: Update status flags and implementations for PSX CD-Rom. Added SEEKERROR and IDERROR status. Set StatP to account for SEEKS, READS and shell open. Added speed to cdrom struct instead of cdvd. Adjustments to cdlPlay to be in line with No$ description. Added MODE_INIT. Removed old needless hack. Added ToDo in cdlPlay --- pcsx2/CDVD/CdRom.cpp | 55 +++++++++++++++++++++++--------------------- pcsx2/CDVD/CdRom.h | 1 + 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/pcsx2/CDVD/CdRom.cpp b/pcsx2/CDVD/CdRom.cpp index 045f7427dc..8c032c980f 100644 --- a/pcsx2/CDVD/CdRom.cpp +++ b/pcsx2/CDVD/CdRom.cpp @@ -41,7 +41,7 @@ enum cdrom_registers CdlDemute = 12, CdlSetfilter = 13, CdlSetmode = 14, - CdlGetmode = 15, + CdlGetparam = 15, CdlGetlocL = 16, CdlGetlocP = 17, Cdl18 = 18, @@ -54,7 +54,6 @@ enum cdrom_registers CdlReadS = 27, CdlReset = 28, CdlReadToc = 30, - AUTOPAUSE = 249, READ_ACK = 250, READ = 251, @@ -68,7 +67,7 @@ const char* CmdName[0x100] = { "CdlSync", "CdlNop", "CdlSetloc", "CdlPlay", "CdlForward", "CdlBackward", "CdlReadN", "CdlStandby", "CdlStop", "CdlPause", "CdlInit", "CdlMute", - "CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetmode", + "CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetparam", "CdlGetlocL", "CdlGetlocP", "Cdl18", "CdlGetTN", "CdlGetTD", "CdlSeekL", "CdlSeekP", NULL, NULL, "CdlTest", "CdlID", "CdlReadS", @@ -93,6 +92,7 @@ u8 Test23[] = {0x43, 0x58, 0x44, 0x32, 0x39, 0x34, 0x30, 0x51}; #define DiskError 5 /* Modes flags */ +#define MODE_INIT (0 << 0) // Init sets mode 00h or not all bits cleared #define MODE_SPEED (1 << 7) // 0x80 #define MODE_STRSND (1 << 6) // 0x40 ADPCM on/off #define MODE_SIZE_2340 (1 << 5) // 0x20 @@ -108,8 +108,8 @@ u8 Test23[] = {0x43, 0x58, 0x44, 0x32, 0x39, 0x34, 0x30, 0x51}; #define STATUS_SEEK (1 << 6) // 0x40 #define STATUS_READ (1 << 5) // 0x20 #define STATUS_SHELLOPEN (1 << 4) // 0x10 -#define STATUS_UNKNOWN3 (1 << 3) // 0x08 -#define STATUS_UNKNOWN2 (1 << 2) // 0x04 +#define STATUS_IDERROR (1 << 3) // 0x08 +#define STATUS_SEEKERROR (1 << 2) // 0x04 #define STATUS_ROTATING (1 << 1) // 0x02 #define STATUS_ERROR (1 << 0) // 0x01 @@ -134,6 +134,8 @@ static void AddIrqQueue(u8 irq, u32 ecycle); static __fi void StartReading(u32 type) { cdr.Reading = type; + // Read's retry. If there's a status error clear and try, try again + cdr.StatP &~ STATUS_ERROR; cdr.FirstSector = 1; cdr.Readed = 0xff; //DevCon.Warning("ReadN/ReadS delay: %d", sectorSeekReadDelay); @@ -217,6 +219,7 @@ void cdrInterrupt() case CdlNop: SetResultSize(1); + cdr.StatP &= ~STATUS_SHELLOPEN; cdr.Result[0] = cdr.StatP; cdr.Stat = Acknowledge; break; @@ -256,7 +259,14 @@ void cdrInterrupt() case CdlStandby: cdr.CmdProcess = 0; SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; + if (cdr.StatP & STATUS_ROTATING) + { + cdr.StatP |= ERROR_INVALIDARG; + } + else + { + cdr.StatP |= STATUS_ROTATING; + } cdr.Result[0] = cdr.StatP; cdr.Stat = Complete; break; @@ -288,6 +298,7 @@ void cdrInterrupt() case CdlInit: SetResultSize(1); cdr.StatP = STATUS_ROTATING; + cdr.Mode |= MODE_INIT; cdr.Result[0] = cdr.StatP; cdr.Stat = Acknowledge; AddIrqQueue(CdlInit + 0x20, 0x800); @@ -328,7 +339,7 @@ void cdrInterrupt() cdr.Stat = Acknowledge; break; - case CdlGetmode: + case CdlGetparam: SetResultSize(6); cdr.StatP |= STATUS_ROTATING; cdr.Result[0] = cdr.StatP; @@ -555,7 +566,8 @@ void cdrReadInterrupt() cdr.OCUP = 1; SetResultSize(1); - cdr.StatP |= STATUS_READ | STATUS_ROTATING; + cdr.StatP &= ~STATUS_SEEK; + cdr.StatP |= STATUS_READ; cdr.Result[0] = cdr.StatP; if (cdr.RErr == 0) @@ -573,7 +585,8 @@ void cdrReadInterrupt() DevCon.Warning("CD err"); memzero(cdr.Transfer); cdr.Stat = DiskError; - cdr.Result[0] |= STATUS_ERROR; + cdr.StatP |= STATUS_ERROR; + cdr.Result[0] = cdr.StatP; ReadTrack(); CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); return; @@ -730,6 +743,7 @@ void cdrWrite1(u8 rt) //StopReading(); // Setloc is memorizing the wanted target, and marks it as unprocessed, and has no other effect // (it doesn't start reading or seeking, and doesn't interrupt or redirect any active reads). + // But it does set the seek target. This is used to set the target then seperately start the seek after setloc int oldSector = msf_to_lsn(cdr.SetSector); for (i = 0; i < 3; i++) cdr.SetSector[i] = btoi(cdr.Param[i]); @@ -752,13 +766,7 @@ void cdrWrite1(u8 rt) AddIrqQueue(cdr.Cmd, 0x800); // the seek delay occurs on the next read / seek command (CdlReadS, CdlSeekL, etc) } break; - do_CdlPlay: case CdlPlay: - // Taken from pcsxr - if (cdr.Reading) - { - StopReading(); - } if (cdr.SetlocPending) { memcpy(cdr.SetSectorSeek, cdr.SetSector, 4); @@ -767,6 +775,8 @@ void cdrWrite1(u8 rt) cdr.Play = 1; cdr.Ctrl |= 0x80; cdr.Stat = NoIntr; + // Play is almost identical to CdlReadS, believe it or not. The main difference is that this does not trigger a completed read IRQ + StartReading(2); AddIrqQueue(cdr.Cmd, 0x800); break; @@ -795,8 +805,6 @@ void cdrWrite1(u8 rt) break; case CdlStandby: - StopCdda(); - StopReading(); cdr.Ctrl |= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); @@ -851,22 +859,21 @@ void cdrWrite1(u8 rt) case CdlSetmode: CDVD_LOG("Setmode %x", cdr.Param[0]); - cdr.Mode = cdr.Param[0]; cdr.Ctrl |= 0x80; cdr.Stat = NoIntr; + cdr.Speed = 1 + ((cdr.Mode >> 7) & 0x1); if (cdr.Mode & MODE_CDDA) { StopCdda(); - cdvd.Type = CDVD_TYPE_CDDA; + cdvd.Type = CDVD_TYPE_PSCDDA; } - cdvd.Speed = 1 + ((cdr.Mode >> 7) & 0x1); setPs1CDVDSpeed(cdvd.Speed); AddIrqQueue(cdr.Cmd, 0x800); break; - case CdlGetmode: + case CdlGetparam: cdr.Ctrl |= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); @@ -929,8 +936,6 @@ void cdrWrite1(u8 rt) break; case CdlReadS: - if (cdvd.Type == CDVD_TYPE_PSCDDA) // Taken from pcsxr - goto do_CdlPlay; cdr.Irq = 0; StopReading(); cdr.Ctrl |= 0x80; @@ -1065,9 +1070,7 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) if (cdr.Readed == 0) { DevCon.Warning("*** DMA 3 *** NOT READY"); - HW_DMA3_CHCR &= ~0x01000000; //hack - psxDmaInterrupt(3); //hack - return; + break; } cdsize = (bcr & 0xffff) * 4; diff --git a/pcsx2/CDVD/CdRom.h b/pcsx2/CDVD/CdRom.h index 0197f5529e..c4e6406d0e 100644 --- a/pcsx2/CDVD/CdRom.h +++ b/pcsx2/CDVD/CdRom.h @@ -69,6 +69,7 @@ struct cdrStruct u8 SetSectorSeek[4]; u8 Track; int Play; + int Speed; int CurTrack; int Mode, File, Channel, Muted; int Reset;