CdlSync should be NULL and return an error. (#199)
[pcsx_rearmed.git] / libpcsxcore / cdrom.c
index 3a2eb1f..1e8f950 100644 (file)
@@ -24,6 +24,7 @@
 #include "cdrom.h"
 #include "ppf.h"
 #include "psxdma.h"
+#include "arm_features.h"
 
 /* logging */
 #if 0
@@ -47,7 +48,7 @@ cdrStruct cdr;
 static unsigned char *pTransfer;
 
 /* CD-ROM magic numbers */
-#define CdlSync        0
+#define CdlSync        0  /* nocash documentation : "Uh, actually, returns error code 40h = Invalid Command...?" */
 #define CdlNop         1
 #define CdlSetloc      2
 #define CdlPlay        3
@@ -495,6 +496,7 @@ void cdrPlayInterrupt()
                if (cdr.SetlocPending) {
                        memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
                        cdr.SetlocPending = 0;
+                       cdr.m_locationChanged = TRUE;
                }
                Find_CurTrack(cdr.SetSectorPlay);
                ReadTrack(cdr.SetSectorPlay);
@@ -526,7 +528,15 @@ void cdrPlayInterrupt()
                }
        }
 
-       CDRMISC_INT(cdReadTime);
+       if (cdr.m_locationChanged)
+       {
+               CDRMISC_INT(cdReadTime * 30);
+               cdr.m_locationChanged = FALSE;
+       }
+       else
+       {
+               CDRMISC_INT(cdReadTime);
+       }
 
        // update for CdlGetlocP/autopause
        generate_subq(cdr.SetSectorPlay);
@@ -538,6 +548,7 @@ void cdrInterrupt() {
        int start_rotating = 0;
        int error = 0;
        int delay;
+       unsigned int seekTime = 0;
 
        // Reschedule IRQ
        if (cdr.Stat) {
@@ -564,10 +575,6 @@ void cdrInterrupt() {
        cdr.Irq = 0;
 
        switch (Irq) {
-               case CdlSync:
-                       // TOOD: sometimes/always return error?
-                       break;
-
                case CdlNop:
                        if (cdr.DriveState != DRIVESTATE_LID_OPEN)
                                cdr.StatP &= ~STATUS_SHELLOPEN;
@@ -587,6 +594,7 @@ void cdrInterrupt() {
                        if (cdr.SetlocPending) {
                                memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
                                cdr.SetlocPending = 0;
+                               cdr.m_locationChanged = TRUE;
                        }
 
                        // BIOS CD Player
@@ -908,8 +916,11 @@ void cdrInterrupt() {
                case CdlReadN:
                case CdlReadS:
                        if (cdr.SetlocPending) {
+                               seekTime = abs(msf2sec(cdr.SetSectorPlay) - msf2sec(cdr.SetSector)) * (cdReadTime / 200);
+                               if(seekTime > 1000000) seekTime = 1000000;
                                memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
                                cdr.SetlocPending = 0;
+                               cdr.m_locationChanged = TRUE;
                        }
                        Find_CurTrack(cdr.SetSectorPlay);
 
@@ -947,7 +958,7 @@ void cdrInterrupt() {
                                // - fix cutscene speech (startup)
 
                                // ??? - use more accurate seek time later
-                               CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1);
+                               CDREAD_INT(((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1) + seekTime);
                        } else {
                                cdr.StatP |= STATUS_READ;
                                cdr.StatP &= ~STATUS_SEEK;
@@ -958,7 +969,7 @@ void cdrInterrupt() {
                        cdr.Result[0] = cdr.StatP;
                        start_rotating = 1;
                        break;
-
+               case CdlSync:
                default:
                        CDR_LOG_I("Invalid command: %02x\n", Irq);
                        error = ERROR_INVALIDCMD;
@@ -1006,7 +1017,7 @@ finish:
 #endif
 }
 
-#ifdef __ARM_ARCH_7A__
+#ifdef HAVE_ARMV7
  #define ssat32_to_16(v) \
   asm("ssat %0,#16,%1" : "=r" (v) : "r" (v))
 #else
@@ -1101,9 +1112,14 @@ void cdrReadInterrupt() {
                        cdr.Channel = cdr.Transfer[4 + 1];
                }
 
+               /* Gameblabla 
+                * Skips playing on channel 255.
+                * Fixes missing audio in Blue's Clues : Blue's Big Musical. (Should also fix Taxi 2)
+                * TODO : Check if this is the proper behaviour.
+                * */
                if((cdr.Transfer[4 + 2] & 0x4) &&
                         (cdr.Transfer[4 + 1] == cdr.Channel) &&
-                        (cdr.Transfer[4 + 0] == cdr.File)) {
+                        (cdr.Transfer[4 + 0] == cdr.File) && cdr.Channel != 255) {
                        int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector);
                        if (!ret) {
                                cdrAttenuate(cdr.Xa.pcm, cdr.Xa.nsamples, cdr.Xa.stereo);
@@ -1126,7 +1142,13 @@ void cdrReadInterrupt() {
 
        cdr.Readed = 0;
 
-       CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime);
+       uint32_t delay = (cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime;
+       if (cdr.m_locationChanged) {
+               CDREAD_INT(delay * 30);
+               cdr.m_locationChanged = FALSE;
+       } else {
+               CDREAD_INT(delay);
+       }
 
        /*
        Croc 2: $40 - only FORM1 (*)
@@ -1413,13 +1435,15 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) {
                        psxCpu->Clear(madr, cdsize / 4);
                        pTransfer += cdsize;
 
-
-                       // burst vs normal
                        if( chcr == 0x11400100 ) {
+                               HW_DMA3_MADR = SWAPu32(madr + cdsize);
                                CDRDMA_INT( (cdsize/4) / 4 );
                        }
                        else if( chcr == 0x11000000 ) {
-                               CDRDMA_INT( (cdsize/4) * 1 );
+                               // CDRDMA_INT( (cdsize/4) * 1 );
+                               // halted
+                               psxRegs.cycle += (cdsize/4) * 24/2;
+                               CDRDMA_INT(16);
                        }
                        return;
 
@@ -1462,6 +1486,8 @@ void cdrReset() {
        cdr.DriveState = DRIVESTATE_STANDBY;
        cdr.StatP = STATUS_ROTATING;
        pTransfer = cdr.Transfer;
+       cdr.SetlocPending = 0;
+       cdr.m_locationChanged = FALSE;
 
        // BIOS player - default values
        cdr.AttenuatorLeftToLeft = 0x80;
@@ -1495,7 +1521,9 @@ int cdrFreeze(void *f, int Mode) {
                pTransfer = cdr.Transfer + tmp;
 
                // read right sub data
-               memcpy(tmpp, cdr.Prev, 3);
+               tmpp[0] = btoi(cdr.Prev[0]);
+               tmpp[1] = btoi(cdr.Prev[1]);
+               tmpp[2] = btoi(cdr.Prev[2]);
                cdr.Prev[0]++;
                ReadTrack(tmpp);