cdrStruct cdr;
static unsigned char *pTransfer;
-static int subq_broken;
/* CD-ROM magic numbers */
#define CdlSync 0
}
}
-static void ReadTrack(const u8 *time, int after_seek) {
+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;
- int track, old_track;
u16 crc;
tmp[0] = itob(time[0]);
cdr.RErr = CDR_readTrack(tmp);
memcpy(cdr.Prev, tmp, 3);
- cdr.TrackChanged = FALSE;
-
if (CheckSBI(time))
return;
subq = (struct SubQ *)CDR_getBufferSub();
- if (subq != NULL && !subq_broken) {
+ if (subq != NULL && cdr.CurTrack == 1) {
crc = calcCrc((u8 *)subq + 12, 10);
- old_track = btoi(cdr.subq.Track);
- track = btoi(subq->TrackNumber);
-
- // track checks are probably wrong, but deals with corrupted
- // subq + good checksum
- // (how does the real thing handle that?)
- if (crc == (((u16)subq->CRC[0] << 8) | subq->CRC[1])
- && (after_seek || track == old_track || track == old_track + 1)) {
+ 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);
-
- if (track == cdr.CurTrack + 1) {
- cdr.CurTrack++;
- cdr.TrackChanged = TRUE;
- }
}
else {
- CDR_LOG_I("ignore subq @%02x:%02x:%02x\n",
+ CDR_LOG_I("subq bad crc @%02x:%02x:%02x\n",
tmp[0], tmp[1], tmp[2]);
}
}
else {
- 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);
-
- 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] = tmp[0];
- cdr.subq.Absolute[1] = tmp[1];
- cdr.subq.Absolute[2] = tmp[2];
+ generate_subq(time);
}
CDR_LOG(" -> %02x,%02x %02x:%02x:%02x %02x:%02x:%02x\n",
memcpy(cdr.SetSectorPlay, cdr.SetSector, 4);
Find_CurTrack(cdr.SetSectorPlay);
- ReadTrack(cdr.SetSectorPlay, 1);
+ ReadTrack(cdr.SetSectorPlay);
cdr.TrackChanged = FALSE;
}
CDRMISC_INT(cdReadTime);
// update for CdlGetlocP/autopause
- ReadTrack(cdr.SetSectorPlay, 0);
+ generate_subq(cdr.SetSectorPlay);
}
void cdrInterrupt() {
- plays tracks without retry play
*/
Find_CurTrack(cdr.SetSectorPlay);
- ReadTrack(cdr.SetSectorPlay, 1);
+ ReadTrack(cdr.SetSectorPlay);
cdr.TrackChanged = FALSE;
if (!Config.Cdda)
// Fighting Force 2 - update subq time immediately
// - fixes new game
- cdr.CurTrack = 1;
- ReadTrack(cdr.SetSector, 1);
+ Find_CurTrack(cdr.SetSector);
+ ReadTrack(cdr.SetSector);
// Crusaders of Might and Magic - update getlocl now
#endif
}
+#ifdef __ARM_ARCH_7A__
+ #define ssat32_to_16(v) \
+ asm("ssat %0,#16,%1" : "=r" (v) : "r" (v))
+#else
+ #define ssat32_to_16(v) do { \
+ if (v < -32768) v = -32768; \
+ else if (v > 32767) v = 32767; \
+ } while (0)
+#endif
+
+void cdrAttenuate(s16 *buf, int samples, int stereo)
+{
+ int i, l, r;
+ int ll = cdr.AttenuatorLeftToLeft;
+ int lr = cdr.AttenuatorLeftToRight;
+ int rl = cdr.AttenuatorRightToLeft;
+ int rr = cdr.AttenuatorRightToRight;
+
+ if (lr == 0 && rl == 0 && 0x78 <= ll && ll <= 0x88 && 0x78 <= rr && rr <= 0x88)
+ return;
+
+ if (!stereo && ll == 0x40 && lr == 0x40 && rl == 0x40 && rr == 0x40)
+ return;
+
+ if (stereo) {
+ for (i = 0; i < samples; i++) {
+ l = buf[i * 2];
+ r = buf[i * 2 + 1];
+ l = (l * ll + r * rl) >> 7;
+ r = (r * rr + l * lr) >> 7;
+ ssat32_to_16(l);
+ ssat32_to_16(r);
+ buf[i * 2] = l;
+ buf[i * 2 + 1] = r;
+ }
+ }
+ else {
+ for (i = 0; i < samples; i++) {
+ l = buf[i];
+ l = l * (ll + rl) >> 7;
+ //r = r * (rr + lr) >> 7;
+ ssat32_to_16(l);
+ //ssat32_to_16(r);
+ buf[i] = l;
+ }
+ }
+}
+
void cdrReadInterrupt() {
u8 *buf;
cdr.Result[0] = cdr.StatP;
cdr.Seeked = SEEK_DONE;
- ReadTrack(cdr.SetSector, 0);
+ ReadTrack(cdr.SetSector);
buf = CDR_getBuffer();
if (buf == NULL)
(cdr.Transfer[4 + 1] == cdr.Channel) &&
(cdr.Transfer[4 + 0] == cdr.File)) {
int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector);
-
if (!ret) {
- // only handle attenuator basic channel switch for now
- if (cdr.Xa.stereo) {
- int i;
- if ((cdr.AttenuatorLeft[0] | cdr.AttenuatorLeft[1])
- && !(cdr.AttenuatorRight[0] | cdr.AttenuatorRight[1]))
- {
- for (i = 0; i < cdr.Xa.nsamples; i++)
- cdr.Xa.pcm[i*2 + 1] = cdr.Xa.pcm[i*2];
- }
- else if (!(cdr.AttenuatorLeft[0] | cdr.AttenuatorLeft[1])
- && (cdr.AttenuatorRight[0] | cdr.AttenuatorRight[1]))
- {
- for (i = 0; i < cdr.Xa.nsamples; i++)
- cdr.Xa.pcm[i*2] = cdr.Xa.pcm[i*2 + 1];
- }
- }
+ cdrAttenuate(cdr.Xa.pcm, cdr.Xa.nsamples, cdr.Xa.stereo);
SPU_playADPCMchannel(&cdr.Xa);
cdr.FirstSector = 0;
}
// update for CdlGetlocP
- ReadTrack(cdr.SetSector, 0);
+ ReadTrack(cdr.SetSector);
Check_Shell(0);
}
case 0:
break;
case 3:
- cdr.AttenuatorRight[1] = rt;
+ cdr.AttenuatorRightToRightT = rt;
return;
default:
return;
setIrq();
return;
case 2:
- cdr.AttenuatorLeft[0] = rt;
+ cdr.AttenuatorLeftToLeftT = rt;
return;
case 3:
- cdr.AttenuatorRight[0] = rt;
+ cdr.AttenuatorRightToLeftT = rt;
return;
}
}
cdr.ParamC = 0;
return;
case 2:
- cdr.AttenuatorLeft[1] = rt;
+ cdr.AttenuatorLeftToRightT = rt;
return;
case 3:
- if (rt == 0x20)
- CDR_LOG( "CD-XA Volume: %X %X | %X %X\n",
- cdr.AttenuatorLeft[0], cdr.AttenuatorLeft[1],
- cdr.AttenuatorRight[0], cdr.AttenuatorRight[1] );
+ if (rt & 0x20) {
+ memcpy(&cdr.AttenuatorLeftToLeft, &cdr.AttenuatorLeftToLeftT, 4);
+ CDR_LOG_I("CD-XA Volume: %02x %02x | %02x %02x\n",
+ cdr.AttenuatorLeftToLeft, cdr.AttenuatorLeftToRight,
+ cdr.AttenuatorRightToLeft, cdr.AttenuatorRightToRight);
+ }
return;
}
static void getCdInfo(void)
{
- unsigned int i, j, sector;
- struct SubQ *subq;
- u8 tmpp[3];
u8 tmp;
CDR_getTN(cdr.ResultTN);
tmp = cdr.SetSectorEnd[0];
cdr.SetSectorEnd[0] = cdr.SetSectorEnd[2];
cdr.SetSectorEnd[2] = tmp;
-
- subq_broken = 0;
- subq = (struct SubQ *)CDR_getBufferSub();
- if (subq != NULL && cdr.ResultTN[1] >= 2) {
- CDR_getTD(cdr.ResultTN[1], tmpp);
- sector = fsm2sec(tmpp) - 33;
- for (i = 0; i < 5; i++, sector += 2) {
- sec2msf(sector, tmpp);
- for (j = 0; j < 3; j++)
- tmpp[j] = itob(tmpp[j]);
- CDR_readTrack(tmpp);
- subq = (struct SubQ *)CDR_getBufferSub();
- if (subq->IndexNumber == 0)
- break;
- }
- if (i == 5) {
- SysPrintf("cdrom: subchannel data looks broken, not using it\n");
- subq_broken = 1;
- }
- }
}
void cdrReset() {
pTransfer = cdr.Transfer;
// BIOS player - default values
- cdr.AttenuatorLeft[0] = 0x80;
- cdr.AttenuatorLeft[1] = 0x00;
- cdr.AttenuatorRight[0] = 0x00;
- cdr.AttenuatorRight[1] = 0x80;
+ cdr.AttenuatorLeftToLeft = 0x80;
+ cdr.AttenuatorLeftToRight = 0x00;
+ cdr.AttenuatorRightToLeft = 0x00;
+ cdr.AttenuatorRightToRight = 0x80;
getCdInfo();
}
// read right sub data
memcpy(tmpp, cdr.Prev, 3);
cdr.Prev[0]++;
- ReadTrack(tmpp, 1);
+ ReadTrack(tmpp);
if (cdr.Play) {
Find_CurTrack(cdr.SetSectorPlay);