cdrom: set proper reset values
[pcsx_rearmed.git] / libpcsxcore / cdrom.c
index 78db291..3117a9b 100644 (file)
@@ -108,6 +108,7 @@ unsigned char Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 };
 #define MODE_STRSND      (1<<6) // 0x40 ADPCM on/off
 #define MODE_SIZE_2340   (1<<5) // 0x20
 #define MODE_SIZE_2328   (1<<4) // 0x10
+#define MODE_SIZE_2048   (0<<4) // 0x00
 #define MODE_SF          (1<<3) // 0x08 channel on/off
 #define MODE_REPORT      (1<<2) // 0x04
 #define MODE_AUTOPAUSE   (1<<1) // 0x02
@@ -124,7 +125,6 @@ unsigned char Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 };
 #define STATUS_ERROR     (1<<0) // 0x01
 
 
-
 // 1x = 75 sectors per second
 // PSXCLK = 1 sec in the ps
 // so (PSXCLK / 75) = cdr read time (linuzappz)
@@ -394,6 +394,55 @@ static void Find_CurTrack(const u8 *time)
        }
 }
 
+static void generate_subq(const u8 *time)
+{
+       unsigned char start[3], next[3];
+       unsigned int this_s, start_s, next_s, pregap;
+       int relative_s;
+
+       CDR_getTD(cdr.CurTrack, start);
+       if (cdr.CurTrack + 1 <= cdr.ResultTN[1]) {
+               pregap = 150;
+               CDR_getTD(cdr.CurTrack + 1, next);
+       }
+       else {
+               // last track - cd size
+               pregap = 0;
+               next[0] = cdr.SetSectorEnd[2];
+               next[1] = cdr.SetSectorEnd[1];
+               next[2] = cdr.SetSectorEnd[0];
+       }
+
+       this_s = msf2sec(time);
+       start_s = fsm2sec(start);
+       next_s = fsm2sec(next);
+
+       cdr.TrackChanged = FALSE;
+
+       if (next_s - this_s < pregap) {
+               cdr.TrackChanged = TRUE;
+               cdr.CurTrack++;
+               start_s = next_s;
+       }
+
+       cdr.subq.Index = 1;
+
+       relative_s = this_s - start_s;
+       if (relative_s < 0) {
+               cdr.subq.Index = 0;
+               relative_s = -relative_s;
+       }
+       sec2msf(relative_s, cdr.subq.Relative);
+
+       cdr.subq.Track = itob(cdr.CurTrack);
+       cdr.subq.Relative[0] = itob(cdr.subq.Relative[0]);
+       cdr.subq.Relative[1] = itob(cdr.subq.Relative[1]);
+       cdr.subq.Relative[2] = itob(cdr.subq.Relative[2]);
+       cdr.subq.Absolute[0] = itob(time[0]);
+       cdr.subq.Absolute[1] = itob(time[1]);
+       cdr.subq.Absolute[2] = itob(time[2]);
+}
+
 static void ReadTrack(const u8 *time) {
        unsigned char tmp[3];
        struct SubQ *subq;
@@ -411,73 +460,25 @@ static void ReadTrack(const u8 *time) {
        cdr.RErr = CDR_readTrack(tmp);
        memcpy(cdr.Prev, tmp, 3);
 
-       cdr.TrackChanged = FALSE;
-
        if (CheckSBI(time))
                return;
 
        subq = (struct SubQ *)CDR_getBufferSub();
-       if (subq != NULL) {
+       if (subq != NULL && cdr.CurTrack == 1) {
                crc = calcCrc((u8 *)subq + 12, 10);
                if (crc == (((u16)subq->CRC[0] << 8) | subq->CRC[1])) {
                        cdr.subq.Track = subq->TrackNumber;
                        cdr.subq.Index = subq->IndexNumber;
                        memcpy(cdr.subq.Relative, subq->TrackRelativeAddress, 3);
                        memcpy(cdr.subq.Absolute, subq->AbsoluteAddress, 3);
-
-                       // .. + 1 is probably wrong, but deals with corrupted
-                       // subq + good checksum
-                       // (how does real thing handle that?)
-                       if (cdr.CurTrack + 1 == btoi(subq->TrackNumber)) {
-                               cdr.CurTrack++;
-                               cdr.TrackChanged = TRUE;
-                       }
-               }
-       }
-       else {
-               unsigned char start[3], next[3];
-               unsigned int this_s, start_s, next_s, pregap;
-               int relative_s;
-
-               CDR_getTD(cdr.CurTrack, start);
-               if (cdr.CurTrack + 1 <= cdr.ResultTN[1]) {
-                       pregap = 150;
-                       CDR_getTD(cdr.CurTrack + 1, next);
                }
                else {
-                       // last track - cd size
-                       pregap = 0;
-                       next[0] = cdr.SetSectorEnd[2];
-                       next[1] = cdr.SetSectorEnd[1];
-                       next[2] = cdr.SetSectorEnd[0];
-               }
-
-               this_s = msf2sec(time);
-               start_s = fsm2sec(start);
-               next_s = fsm2sec(next);
-
-               if (next_s - this_s < pregap) {
-                       cdr.TrackChanged = TRUE;
-                       cdr.CurTrack++;
-                       start_s = next_s;
-               }
-
-               cdr.subq.Index = 1;
-
-               relative_s = this_s - start_s;
-               if (relative_s < 0) {
-                       cdr.subq.Index = 0;
-                       relative_s = -relative_s;
+                       CDR_LOG_I("subq bad crc @%02x:%02x:%02x\n",
+                               tmp[0], tmp[1], tmp[2]);
                }
-               sec2msf(relative_s, cdr.subq.Relative);
-
-               cdr.subq.Track = itob(cdr.CurTrack);
-               cdr.subq.Relative[0] = itob(cdr.subq.Relative[0]);
-               cdr.subq.Relative[1] = itob(cdr.subq.Relative[1]);
-               cdr.subq.Relative[2] = itob(cdr.subq.Relative[2]);
-               cdr.subq.Absolute[0] = tmp[0];
-               cdr.subq.Absolute[1] = tmp[1];
-               cdr.subq.Absolute[2] = tmp[2];
+       }
+       else {
+               generate_subq(time);
        }
 
        CDR_LOG(" -> %02x,%02x %02x:%02x:%02x %02x:%02x:%02x\n",
@@ -594,7 +595,7 @@ void cdrPlayInterrupt()
        CDRMISC_INT(cdReadTime);
 
        // update for CdlGetlocP/autopause
-       ReadTrack(cdr.SetSectorPlay);
+       generate_subq(cdr.SetSectorPlay);
 }
 
 void cdrInterrupt() {
@@ -616,7 +617,7 @@ void cdrInterrupt() {
                        SetResultSize(1);
                        cdr.StatP |= STATUS_ROTATING;
                        cdr.Result[0] = cdr.StatP;
-                       cdr.Stat = Acknowledge; 
+                       cdr.Stat = Acknowledge;
                        break;
 
                case CdlNop:
@@ -940,34 +941,23 @@ void cdrInterrupt() {
 
                case CdlID + 0x20:
                        SetResultSize(8);
+                       cdr.Result[0] = cdr.StatP;
+                       cdr.Result[1] = 0;
+                       cdr.Result[2] = 0;
+                       cdr.Result[3] = 0;
 
+                       // 0x10 - audio | 0x80 - unlicensed
                        if (CDR_getStatus(&stat) == -1) {
-                               cdr.Result[0] = 0x00; // 0x08 and cdr.Result[1]|0x10 : audio cd, enters cd player
                                cdr.Result[1] = 0x80; // 0x80 leads to the menu in the bios, else loads CD
                        }
                        else {
-                               if (stat.Type == 2) {
-                                       // Music CD
-                                       cdr.Result[0] = 0x08;
-                                       cdr.Result[1] = 0x10;
-
+                               if (stat.Type == 2)
+                                       cdr.Result[1] |= 0x10;
+                               if (CdromId[0] == '\0')
                                        cdr.Result[1] |= 0x80;
-                               }
-                               else {
-                                       // Data CD
-                                       if (CdromId[0] == '\0') {
-                                               cdr.Result[0] = 0x00;
-                                               cdr.Result[1] = 0x80;
-                                       }
-                                       else {
-                                               cdr.Result[0] = 0x08;
-                                               cdr.Result[1] = 0x00;
-                                       }
-                               }
                        }
+                       cdr.Result[0] |= (cdr.Result[1] >> 4) & 0x08;
 
-                       cdr.Result[2] = 0x00;
-                       cdr.Result[3] = 0x00;
                        strncpy((char *)&cdr.Result[4], "PCSX", 4);
                        cdr.Stat = Complete;
                        break;
@@ -999,7 +989,7 @@ void cdrInterrupt() {
                        cdr.StatP |= STATUS_ROTATING;
                        cdr.Result[0] = cdr.StatP;
                        cdr.Stat = Acknowledge;
-                       AddIrqQueue(CdlReadToc + 0x20, 0x800);
+                       AddIrqQueue(CdlReadToc + 0x20, cdReadTime * 16);
                        break;
 
                case CdlReadToc + 0x20:
@@ -1015,7 +1005,7 @@ void cdrInterrupt() {
 
                        // Fighting Force 2 - update subq time immediately
                        // - fixes new game
-                       cdr.CurTrack = 1;
+                       Find_CurTrack(cdr.SetSector);
                        ReadTrack(cdr.SetSector);
 
 
@@ -1067,14 +1057,62 @@ void cdrInterrupt() {
        setIrq();
 
 #ifdef CDR_LOG_CMD_IRQ
-       SysPrintf("cdrInterrupt() Log: CDR Interrupt IRQ %d %02x: ",
-               cdr.Stat != NoIntr && cdr.Reg2 != 0x18, Irq);
+       SysPrintf("IRQ %d cmd %02x stat %02x: ",
+               !!(cdr.Stat & cdr.Reg2), Irq, cdr.Stat);
        for (i = 0; i < cdr.ResultC; i++)
                SysPrintf("%02x ", cdr.Result[i]);
        SysPrintf("\n");
 #endif
 }
 
+#ifdef __ARM_ARCH_7A__
+ #define ssat32_to_16(v) \
+  asm("ssat %0,#16,%1" : "=r" (v) : "r" (v))
+#else
+ #define ssat32_to_16(v) do { \
+  if (v < -32768) v = -32768; \
+  else if (v > 32767) v = 32767; \
+ } while (0)
+#endif
+
+void cdrAttenuate(s16 *buf, int samples, int stereo)
+{
+       int i, l, r;
+       int ll = cdr.AttenuatorLeftToLeft;
+       int lr = cdr.AttenuatorLeftToRight;
+       int rl = cdr.AttenuatorRightToLeft;
+       int rr = cdr.AttenuatorRightToRight;
+
+       if (lr == 0 && rl == 0 && 0x78 <= ll && ll <= 0x88 && 0x78 <= rr && rr <= 0x88)
+               return;
+
+       if (!stereo && ll == 0x40 && lr == 0x40 && rl == 0x40 && rr == 0x40)
+               return;
+
+       if (stereo) {
+               for (i = 0; i < samples; i++) {
+                       l = buf[i * 2];
+                       r = buf[i * 2 + 1];
+                       l = (l * ll + r * rl) >> 7;
+                       r = (r * rr + l * lr) >> 7;
+                       ssat32_to_16(l);
+                       ssat32_to_16(r);
+                       buf[i * 2] = l;
+                       buf[i * 2 + 1] = r;
+               }
+       }
+       else {
+               for (i = 0; i < samples; i++) {
+                       l = buf[i];
+                       l = l * (ll + rl) >> 7;
+                       //r = r * (rr + lr) >> 7;
+                       ssat32_to_16(l);
+                       //ssat32_to_16(r);
+                       buf[i] = l;
+               }
+       }
+}
+
 void cdrReadInterrupt() {
        u8 *buf;
 
@@ -1094,7 +1132,7 @@ void cdrReadInterrupt() {
        cdr.Result[0] = cdr.StatP;
        cdr.Seeked = SEEK_DONE;
 
-       ReadTrack( cdr.SetSector );
+       ReadTrack(cdr.SetSector);
 
        buf = CDR_getBuffer();
        if (buf == NULL)
@@ -1122,40 +1160,14 @@ void cdrReadInterrupt() {
                        cdr.Channel = cdr.Transfer[4 + 1];
                }
 
-               if ((cdr.Transfer[4 + 2] & 0x4) &&
+               if((cdr.Transfer[4 + 2] & 0x4) &&
                         (cdr.Transfer[4 + 1] == cdr.Channel) &&
-                       (cdr.Transfer[4 + 0] == cdr.File)) {
+                        (cdr.Transfer[4 + 0] == cdr.File)) {
                        int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector);
-
                        if (!ret) {
-                               // only handle attenuator basic channel switch for now
-                               if (cdr.Xa.stereo) {
-                                       int i;
-                                       if ((cdr.AttenuatorLeft[0] | cdr.AttenuatorLeft[1])
-                                           && !(cdr.AttenuatorRight[0] | cdr.AttenuatorRight[1]))
-                                       {
-                                               for (i = 0; i < cdr.Xa.nsamples; i++)
-                                                       cdr.Xa.pcm[i*2 + 1] = cdr.Xa.pcm[i*2];
-                                       }
-                                       else if (!(cdr.AttenuatorLeft[0] | cdr.AttenuatorLeft[1])
-                                           && (cdr.AttenuatorRight[0] | cdr.AttenuatorRight[1]))
-                                       {
-                                               for (i = 0; i < cdr.Xa.nsamples; i++)
-                                                       cdr.Xa.pcm[i*2] = cdr.Xa.pcm[i*2 + 1];
-                                       }
-                               }
-
+                               cdrAttenuate(cdr.Xa.pcm, cdr.Xa.nsamples, cdr.Xa.stereo);
                                SPU_playADPCMchannel(&cdr.Xa);
                                cdr.FirstSector = 0;
-
-#if 0
-                               // Crash Team Racing: music, speech
-                               // - done using cdda decoded buffer (spu irq)
-                               // - don't do here
-
-                               // signal ADPCM data ready
-                               setIrq();
-#endif
                        }
                        else cdr.FirstSector = -1;
                }
@@ -1252,7 +1264,7 @@ void cdrWrite1(unsigned char rt) {
        case 0:
                break;
        case 3:
-               cdr.AttenuatorRight[1] = rt;
+               cdr.AttenuatorRightToRightT = rt;
                return;
        default:
                return;
@@ -1262,7 +1274,7 @@ void cdrWrite1(unsigned char rt) {
        cdr.OCUP = 0;
 
 #ifdef CDR_LOG_CMD_IRQ
-       SysPrintf("cdrWrite1() Log: CD1 write: %x (%s)", rt, CmdName[rt]);
+       SysPrintf("CD1 write: %x (%s)", rt, CmdName[rt]);
        if (cdr.ParamC) {
                SysPrintf(" Param[%d] = {", cdr.ParamC);
                for (i = 0; i < cdr.ParamC; i++)
@@ -1316,23 +1328,8 @@ void cdrWrite1(unsigned char rt) {
                // Vib Ribbon: try same track again
                StopCdda();
 
-#if 0
-               if (!cdr.SetSector[0] & !cdr.SetSector[1] & !cdr.SetSector[2]) {
-                       if (CDR_getTN(cdr.ResultTN) != -1) {
-                               if (cdr.CurTrack > cdr.ResultTN[1])
-                                       cdr.CurTrack = cdr.ResultTN[1];
-                               if (CDR_getTD((unsigned char)(cdr.CurTrack), cdr.ResultTD) != -1) {
-                                       int tmp = cdr.ResultTD[2];
-                                       cdr.ResultTD[2] = cdr.ResultTD[0];
-                                       cdr.ResultTD[0] = tmp;
-                                       if (!Config.Cdda) CDR_play(cdr.ResultTD);
-                               }
-                       }
-               }
-#endif
                // Vib Ribbon - decoded buffer IRQ for CDDA reading
                // - fixes ribbon timing + music CD mode
-               //TODO?
                //CDRDBUF_INT( PSXCLK / 44100 * 0x100 );
 
                cdr.Play = TRUE;
@@ -1473,10 +1470,10 @@ void cdrWrite2(unsigned char rt) {
                setIrq();
                return;
        case 2:
-               cdr.AttenuatorLeft[0] = rt;
+               cdr.AttenuatorLeftToLeftT = rt;
                return;
        case 3:
-               cdr.AttenuatorRight[0] = rt;
+               cdr.AttenuatorRightToLeftT = rt;
                return;
        }
 }
@@ -1504,13 +1501,15 @@ void cdrWrite3(unsigned char rt) {
                        cdr.ParamC = 0;
                return;
        case 2:
-               cdr.AttenuatorLeft[1] = rt;
+               cdr.AttenuatorLeftToRightT = rt;
                return;
        case 3:
-               if (rt == 0x20)
-               CDR_LOG( "CD-XA Volume: %X %X | %X %X\n",
-                       cdr.AttenuatorLeft[0], cdr.AttenuatorLeft[1],
-                       cdr.AttenuatorRight[0], cdr.AttenuatorRight[1] );
+               if (rt & 0x20) {
+                       memcpy(&cdr.AttenuatorLeftToLeft, &cdr.AttenuatorLeftToLeftT, 4);
+                       CDR_LOG_I("CD-XA Volume: %02x %02x | %02x %02x\n",
+                               cdr.AttenuatorLeftToLeft, cdr.AttenuatorLeftToRight,
+                               cdr.AttenuatorRightToLeft, cdr.AttenuatorRightToRight);
+               }
                return;
        }
 
@@ -1555,10 +1554,11 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) {
                        // - fix boot
                        if( cdsize == 0 )
                        {
-                               switch (cdr.Mode & 0x30) {
-                                       case 0x00: cdsize = 2048; break;
-                                       case MODE_SIZE_2328: cdsize = 2328; break;
+                               switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) {
                                        case MODE_SIZE_2340: cdsize = 2340; break;
+                                       case MODE_SIZE_2328: cdsize = 2328; break;
+                                       default:
+                                       case MODE_SIZE_2048: cdsize = 2048; break;
                                }
                        }
 
@@ -1630,13 +1630,15 @@ void cdrReset() {
        cdr.CurTrack = 1;
        cdr.File = 1;
        cdr.Channel = 1;
+       cdr.Reg2 = 0x1f;
+       cdr.Stat = NoIntr;
        pTransfer = cdr.Transfer;
 
        // BIOS player - default values
-       cdr.AttenuatorLeft[0] = 0x80;
-       cdr.AttenuatorLeft[1] = 0x00;
-       cdr.AttenuatorRight[0] = 0x00;
-       cdr.AttenuatorRight[1] = 0x80;
+       cdr.AttenuatorLeftToLeft = 0x80;
+       cdr.AttenuatorLeftToRight = 0x00;
+       cdr.AttenuatorRightToLeft = 0x00;
+       cdr.AttenuatorRightToRight = 0x80;
 
        getCdInfo();
 }