Proper CDDA fix for Fantastic Pinball Kyuutenkai (and remove CDDA playthread as it...
[pcsx_rearmed.git] / libpcsxcore / cdrom.c
index 95e739f..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...?" */
@@ -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;