Proper CDDA fix for Fantastic Pinball Kyuutenkai (and remove CDDA playthread as it...
[pcsx_rearmed.git] / libpcsxcore / cdrom.c
index 5a596ad..47e4037 100644 (file)
@@ -46,6 +46,7 @@
 
 cdrStruct cdr;
 static unsigned char *pTransfer;
+static s16 read_buf[CD_FRAMESIZE_RAW/2];
 
 /* CD-ROM magic numbers */
 #define CdlSync        0  /* nocash documentation : "Uh, actually, returns error code 40h = Invalid Command...?" */
@@ -58,7 +59,7 @@ static unsigned char *pTransfer;
 #define CdlStandby     7
 #define CdlStop        8
 #define CdlPause       9
-#define CdlInit        10
+#define CdlReset       10
 #define CdlMute        11
 #define CdlDemute      12
 #define CdlSetfilter   13
@@ -76,19 +77,19 @@ static unsigned char *pTransfer;
 #define CdlTest        25
 #define CdlID          26
 #define CdlReadS       27
-#define CdlReset       28
+#define CdlInit        28
 #define CdlGetQ        29
 #define CdlReadToc     30
 
 char *CmdName[0x100]= {
     "CdlSync",     "CdlNop",       "CdlSetloc",  "CdlPlay",
     "CdlForward",  "CdlBackward",  "CdlReadN",   "CdlStandby",
-    "CdlStop",     "CdlPause",     "CdlInit",    "CdlMute",
+    "CdlStop",     "CdlPause",     "CdlReset",    "CdlMute",
     "CdlDemute",   "CdlSetfilter", "CdlSetmode", "CdlGetparam",
     "CdlGetlocL",  "CdlGetlocP",   "CdlReadT",   "CdlGetTN",
     "CdlGetTD",    "CdlSeekL",     "CdlSeekP",   "CdlSetclock",
     "CdlGetclock", "CdlTest",      "CdlID",      "CdlReadS",
-    "CdlReset",    NULL,           "CDlReadToc", NULL
+    "CdlInit",     NULL,           "CDlReadToc", NULL
 };
 
 unsigned char Test04[] = { 0 };
@@ -431,6 +432,10 @@ static void AddIrqQueue(unsigned short irq, unsigned long ecycle) {
 
 static void cdrPlayInterrupt_Autopause()
 {
+       u32 abs_lev_max = 0;
+       boolean abs_lev_chselect;
+       u32 i;
+
        if ((cdr.Mode & MODE_AUTOPAUSE) && cdr.TrackChanged) {
                CDR_LOG( "CDDA STOP\n" );
 
@@ -446,10 +451,20 @@ static void cdrPlayInterrupt_Autopause()
                StopCdda();
        }
        else if (cdr.Mode & MODE_REPORT) {
-
+               CDR_readCDDA(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2], (u8 *)read_buf);
                cdr.Result[0] = cdr.StatP;
                cdr.Result[1] = cdr.subq.Track;
                cdr.Result[2] = cdr.subq.Index;
+               
+               abs_lev_chselect = cdr.subq.Absolute[1] & 0x01;
+               
+               /* 8 is a hack. For accuracy, it should be 588. */
+               for (i = 0; i < 8; i++)
+               {
+                       abs_lev_max = MAX_VALUE(abs_lev_max, abs(read_buf[i * 2 + abs_lev_chselect]));
+               }
+               abs_lev_max = MIN_VALUE(abs_lev_max, 32767);
+               abs_lev_max |= abs_lev_chselect << 15;
 
                if (cdr.subq.Absolute[2] & 0x10) {
                        cdr.Result[3] = cdr.subq.Relative[0];
@@ -462,8 +477,8 @@ static void cdrPlayInterrupt_Autopause()
                        cdr.Result[5] = cdr.subq.Absolute[2];
                }
 
-               cdr.Result[6] = 0;
-               cdr.Result[7] = 0;
+               cdr.Result[6] = abs_lev_max >> 0;
+               cdr.Result[7] = abs_lev_max >> 8;
 
                // Rayman: Logo freeze (resultready + dataready)
                cdr.ResultReady = 1;
@@ -517,6 +532,12 @@ void cdrPlayInterrupt()
                cdrPlayInterrupt_Autopause();
 
        if (!cdr.Play) return;
+       
+       if (CDR_readCDDA && !cdr.Muted && cdr.Mode & MODE_REPORT) {
+               cdrAttenuate((u8 *)read_buf, CD_FRAMESIZE_RAW / 4, 1);
+               if (SPU_playCDDAchannel)
+                       SPU_playCDDAchannel((u8 *)read_buf, CD_FRAMESIZE_RAW);
+       }
 
        cdr.SetSectorPlay[2]++;
        if (cdr.SetSectorPlay[2] == 75) {
@@ -722,7 +743,21 @@ void cdrInterrupt() {
                        InuYasha - Feudal Fairy Tale: slower
                        - Fixes battles
                        */
-                       AddIrqQueue(CdlPause + 0x100, cdReadTime * 3);
+                       /* Gameblabla - Tightening the timings (as taken from Duckstation). 
+                        * The timings from Duckstation are based upon hardware tests.
+                        * Mednafen's timing don't work for Gundam Battle Assault 2 in PAL/50hz mode,
+                        * seems to be timing sensitive as it can depend on the CPU's clock speed.
+                        * */
+                       if (cdr.DriveState != DRIVESTATE_STANDBY)
+                       {
+                               delay = 7000;
+                       }
+                       else
+                       {
+                               delay = (((cdr.Mode & MODE_SPEED) ? 2 : 1) * (1000000));
+                               CDRMISC_INT((cdr.Mode & MODE_SPEED) ? cdReadTime / 2 : cdReadTime);
+                       }
+                       AddIrqQueue(CdlPause + 0x100, delay);
                        cdr.Ctrl |= 0x80;
                        break;
 
@@ -732,13 +767,15 @@ void cdrInterrupt() {
                        cdr.Stat = Complete;
                        break;
 
-               case CdlInit:
-                       AddIrqQueue(CdlInit + 0x100, cdReadTime * 6);
+               case CdlReset:
+                       cdr.Muted = FALSE;
+                       cdr.Mode = 0x20; /* This fixes This is Football 2, Pooh's Party lockups */
+                       AddIrqQueue(CdlReset + 0x100, 4100000);
                        no_busy_error = 1;
                        start_rotating = 1;
                        break;
 
-               case CdlInit + 0x100:
+               case CdlReset + 0x100:
                        cdr.Stat = Complete;
                        break;
 
@@ -890,7 +927,7 @@ void cdrInterrupt() {
                        cdr.Stat = Complete;
                        break;
 
-               case CdlReset:
+               case CdlInit:
                        // yes, it really sets STATUS_SHELLOPEN
                        cdr.StatP |= STATUS_SHELLOPEN;
                        cdr.DriveState = DRIVESTATE_RESCAN_CD;
@@ -1286,8 +1323,8 @@ void cdrWrite1(unsigned char rt) {
                StopReading();
                break;
 
-       case CdlReset:
        case CdlInit:
+       case CdlReset:
                cdr.Seeked = SEEK_DONE;
                StopCdda();
                StopReading();