+static void Check_Shell( int Irq )
+{
+ // check case open/close
+ if (cdr.LidCheck > 0)
+ {
+ CDR_LOG( "LidCheck\n" );
+
+ // $20 = check lid state
+ if( cdr.LidCheck == 0x20 )
+ {
+ u32 i;
+
+ i = stat.Status;
+ if (CDR_getStatus(&stat) != -1)
+ {
+ // BIOS hangs + BIOS error messages
+ //if (stat.Type == 0xff)
+ //cdr.Stat = DiskError;
+
+ // case now open
+ if (stat.Status & STATUS_SHELLOPEN)
+ {
+ // Vib Ribbon: pre-CD swap
+ StopCdda();
+
+
+ // GameShark Lite: Death if DiskError happens
+ //
+ // Vib Ribbon: Needs DiskError for CD swap
+
+ if (Irq != CdlNop)
+ {
+ cdr.Stat = DiskError;
+
+ cdr.StatP |= STATUS_ERROR;
+ cdr.Result[0] |= STATUS_ERROR;
+ }
+
+ // GameShark Lite: Wants -exactly- $10
+ cdr.StatP |= STATUS_SHELLOPEN;
+ cdr.StatP &= ~STATUS_ROTATING;
+
+
+ CDRLID_INT( cdReadTime * 3 );
+ cdr.LidCheck = 0x10;
+
+
+ // GS CDX 3.3 = $11
+ }
+
+ // case just closed
+ else if ( i & STATUS_SHELLOPEN )
+ {
+ cdr.StatP |= STATUS_ROTATING;
+
+ CheckCdrom();
+
+
+ if( cdr.Stat == NoIntr )
+ cdr.Stat = Acknowledge;
+
+ setIrq();
+
+ // begin close-seek-ready cycle
+ CDRLID_INT( cdReadTime * 3 );
+ cdr.LidCheck = 0x30;
+
+
+ // GameShark Lite: Wants -exactly- $42, then $02
+ // GS CDX 3.3: Wants $11/$80, $13/$80, $01/$00
+ }
+
+ // case still closed - wait for recheck
+ else
+ {
+ CDRLID_INT( cdReadTime * 3 );
+ cdr.LidCheck = 0x10;
+ }
+ }
+ }
+
+
+ // GS CDX: clear all values but #1,#2
+ if( (cdr.LidCheck >= 0x30) || (cdr.StatP & STATUS_SHELLOPEN) )
+ {
+ SetResultSize(16);
+ memset( cdr.Result, 0, 16 );
+
+ cdr.Result[0] = cdr.StatP;
+
+
+ // GS CDX: special return value
+ if( cdr.StatP & STATUS_SHELLOPEN )
+ {
+ cdr.Result[1] = 0x80;
+ }
+
+
+ if( cdr.Stat == NoIntr )
+ cdr.Stat = Acknowledge;
+
+ setIrq();
+ }
+ }
+}
+
+static void Find_CurTrack(const u8 *time)
+{
+ int current, sect;
+
+ current = msf2sec(time);
+
+ for (cdr.CurTrack = 1; cdr.CurTrack < cdr.ResultTN[1]; cdr.CurTrack++) {
+ CDR_getTD(cdr.CurTrack + 1, cdr.ResultTD);
+ sect = fsm2sec(cdr.ResultTD);
+ if (sect - current >= 150)
+ break;
+ }
+}
+
+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;
+ u16 crc;
+
+ tmp[0] = itob(time[0]);
+ tmp[1] = itob(time[1]);
+ tmp[2] = itob(time[2]);
+
+ if (memcmp(cdr.Prev, tmp, 3) == 0)
+ return;
+
+ CDR_LOG("ReadTrack *** %02x:%02x:%02x\n", tmp[0], tmp[1], tmp[2]);
+
+ cdr.RErr = CDR_readTrack(tmp);
+ memcpy(cdr.Prev, tmp, 3);
+
+ if (CheckSBI(time))
+ return;
+
+ subq = (struct SubQ *)CDR_getBufferSub();
+ 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);
+ }
+ else {
+ CDR_LOG_I("subq bad crc @%02x:%02x:%02x\n",
+ tmp[0], tmp[1], tmp[2]);
+ }
+ }
+ else {
+ generate_subq(time);
+ }
+
+ CDR_LOG(" -> %02x,%02x %02x:%02x:%02x %02x:%02x:%02x\n",
+ cdr.subq.Track, cdr.subq.Index,
+ cdr.subq.Relative[0], cdr.subq.Relative[1], cdr.subq.Relative[2],
+ cdr.subq.Absolute[0], cdr.subq.Absolute[1], cdr.subq.Absolute[2]);
+}
+
+static void AddIrqQueue(unsigned char irq, unsigned long ecycle) {
+ if (cdr.Irq != 0)
+ CDR_LOG_I("cdr: override cmd %02x -> %02x\n", cdr.Irq, irq);