+static void cdrPlayInterrupt_Autopause()
+{
+ struct SubQ *subq = (struct SubQ *)CDR_getBufferSub();
+ int track_changed = 0;
+ if (subq != NULL ) {
+ // update subq
+ ReadTrack( cdr.SetSectorPlay );
+
+ CDR_LOG( "CDDA SUB - %X:%X:%X\n",
+ subq->AbsoluteAddress[0], subq->AbsoluteAddress[1], subq->AbsoluteAddress[2] );
+
+ /*
+ CDDA Autopause
+
+ Silhouette Mirage ($3)
+ Tomb Raider 1 ($7)
+ */
+
+ // .. + 1 is probably wrong, but deals with corrupted subq + good checksum
+ // (how does real thing handle those?)
+ if( cdr.CurTrack + 1 == btoi( subq->TrackNumber ) )
+ track_changed = 1;
+ } else {
+ Create_Fake_Subq();
+ CDR_LOG( "CDDA FAKE SUB - %d:%d:%d\n",
+ fake_subq_real[0], fake_subq_real[1], fake_subq_real[2] );
+
+ track_changed = fake_subq_change;
+ fake_subq_change = 0;
+ }
+
+ if ((cdr.Mode & MODE_AUTOPAUSE) && track_changed) {
+ CDR_LOG( "CDDA STOP\n" );
+
+ // Magic the Gathering
+ // - looping territory cdda
+
+ // ...?
+ //cdr.ResultReady = 1;
+ //cdr.Stat = DataReady;
+ cdr.Stat = DataEnd;
+ psxHu32ref(0x1070) |= SWAP32((u32)0x4);
+
+ StopCdda();
+ }
+ else if (cdr.Mode & MODE_REPORT) {
+ if (subq != NULL) {
+ CDR_LOG( "REPPLAY SUB - %X:%X:%X\n",
+ subq->AbsoluteAddress[0], subq->AbsoluteAddress[1], subq->AbsoluteAddress[2] );
+
+ // breaks when .sub doesn't have index 0 for some reason (bad rip?)
+ //cdr.CurTrack = btoi( subq->TrackNumber );
+
+ if (subq->AbsoluteAddress[2] & 0xf)
+ return;
+
+ cdr.Result[0] = cdr.StatP;
+ // BIOS CD Player: data already BCD format
+ cdr.Result[1] = subq->TrackNumber;
+ cdr.Result[2] = subq->IndexNumber;
+
+ cdr.Result[3] = subq->AbsoluteAddress[0];
+ cdr.Result[4] = subq->AbsoluteAddress[1];
+ cdr.Result[5] = subq->AbsoluteAddress[2];
+ } else {
+ CDR_LOG( "REPPLAY FAKE - %d:%d:%d\n",
+ fake_subq_real[0], fake_subq_real[1], fake_subq_real[2] );
+
+ if (fake_subq_real[2] & 0xf)
+ return;
+
+ cdr.Result[0] = cdr.StatP;
+ // track # / index #
+ cdr.Result[1] = itob(cdr.CurTrack);
+ cdr.Result[2] = itob(fake_subq_index);
+ // absolute
+ cdr.Result[3] = itob( fake_subq_real[0] );
+ cdr.Result[4] = itob( fake_subq_real[1] );
+ cdr.Result[5] = itob( fake_subq_real[2] );
+ }
+
+ // Rayman: Logo freeze (resultready + dataready)
+ cdr.ResultReady = 1;
+ cdr.Stat = DataReady;
+
+ SetResultSize(8);
+ psxHu32ref(0x1070) |= SWAP32((u32)0x4);
+ }
+}
+
+// also handles seek
+void cdrPlayInterrupt()
+{
+ if (cdr.Seeked == SEEK_DOING_CMD) {
+ if (cdr.Stat) {
+ CDR_LOG_I("cdrom: seek stat hack\n");
+ CDRMISC_INT(0x1000);
+ return;
+ }
+ SetResultSize(1);
+ cdr.StatP |= STATUS_ROTATING;
+ cdr.StatP &= ~STATUS_SEEK;
+ cdr.Result[0] = cdr.StatP;
+ if (cdr.Irq == 0 || cdr.Irq == 0xff) {
+ cdr.Stat = Complete;
+ if (cdr.Reg2 != 0x18)
+ psxHu32ref(0x1070) |= SWAP32(0x4);
+ }
+
+ cdr.Seeked = SEEK_PENDING;
+ CDRMISC_INT(cdReadTime * 20); // ???
+ return;
+ }
+ else if (cdr.Seeked == SEEK_PENDING) {
+ cdr.Seeked = SEEK_DONE;
+ if (!cdr.Play && !cdr.Reading) {
+ memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
+ Find_CurTrack();
+ ReadTrack(cdr.SetSector);
+ }
+ }
+
+ if (!cdr.Play) return;
+
+ CDR_LOG( "CDDA - %d:%d:%d\n",
+ cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
+
+ CDRMISC_INT( cdReadTime );
+
+ if (!cdr.Irq && !cdr.Stat && (cdr.Mode & MODE_CDDA) && (cdr.Mode & (MODE_AUTOPAUSE|MODE_REPORT)))
+ cdrPlayInterrupt_Autopause();
+
+ cdr.SetSectorPlay[2]++;
+ if (cdr.SetSectorPlay[2] == 75) {
+ cdr.SetSectorPlay[2] = 0;
+ cdr.SetSectorPlay[1]++;
+ if (cdr.SetSectorPlay[1] == 60) {
+ cdr.SetSectorPlay[1] = 0;
+ cdr.SetSectorPlay[0]++;
+ }
+ }
+
+ //Check_Shell(0);
+}
+