X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=libpcsxcore%2Fcdrom.c;h=3117a9bd622cd27f0a71da5c86949aa2d31e824e;hp=fdb38ba9dc312ca05157ce9b47626aae843f21a7;hb=a2d3ccb80003794a38ee9183b6f01de189beaff0;hpb=92ca1ba64e939942ab05aaa3d578f0d165634275 diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index fdb38ba9..3117a9bd 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -45,7 +45,6 @@ cdrStruct cdr; static unsigned char *pTransfer; -static int subq_broken; /* CD-ROM magic numbers */ #define CdlSync 0 @@ -109,6 +108,7 @@ unsigned char Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; #define MODE_STRSND (1<<6) // 0x40 ADPCM on/off #define MODE_SIZE_2340 (1<<5) // 0x20 #define MODE_SIZE_2328 (1<<4) // 0x10 +#define MODE_SIZE_2048 (0<<4) // 0x00 #define MODE_SF (1<<3) // 0x08 channel on/off #define MODE_REPORT (1<<2) // 0x04 #define MODE_AUTOPAUSE (1<<1) // 0x02 @@ -125,7 +125,6 @@ unsigned char Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; #define STATUS_ERROR (1<<0) // 0x01 - // 1x = 75 sectors per second // PSXCLK = 1 sec in the ps // so (PSXCLK / 75) = cdr read time (linuzappz) @@ -395,10 +394,58 @@ static void Find_CurTrack(const u8 *time) } } -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]); @@ -413,81 +460,25 @@ static void ReadTrack(const u8 *time, int after_seek) { 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", @@ -572,7 +563,7 @@ void cdrPlayInterrupt() memcpy(cdr.SetSectorPlay, cdr.SetSector, 4); Find_CurTrack(cdr.SetSectorPlay); - ReadTrack(cdr.SetSectorPlay, 1); + ReadTrack(cdr.SetSectorPlay); cdr.TrackChanged = FALSE; } @@ -604,7 +595,7 @@ void cdrPlayInterrupt() CDRMISC_INT(cdReadTime); // update for CdlGetlocP/autopause - ReadTrack(cdr.SetSectorPlay, 0); + generate_subq(cdr.SetSectorPlay); } void cdrInterrupt() { @@ -626,7 +617,7 @@ void cdrInterrupt() { SetResultSize(1); cdr.StatP |= STATUS_ROTATING; cdr.Result[0] = cdr.StatP; - cdr.Stat = Acknowledge; + cdr.Stat = Acknowledge; break; case CdlNop: @@ -686,7 +677,7 @@ void cdrInterrupt() { - plays tracks without retry play */ Find_CurTrack(cdr.SetSectorPlay); - ReadTrack(cdr.SetSectorPlay, 1); + ReadTrack(cdr.SetSectorPlay); cdr.TrackChanged = FALSE; if (!Config.Cdda) @@ -950,34 +941,23 @@ void cdrInterrupt() { case CdlID + 0x20: SetResultSize(8); + cdr.Result[0] = cdr.StatP; + cdr.Result[1] = 0; + cdr.Result[2] = 0; + cdr.Result[3] = 0; + // 0x10 - audio | 0x80 - unlicensed if (CDR_getStatus(&stat) == -1) { - cdr.Result[0] = 0x00; // 0x08 and cdr.Result[1]|0x10 : audio cd, enters cd player cdr.Result[1] = 0x80; // 0x80 leads to the menu in the bios, else loads CD } else { - if (stat.Type == 2) { - // Music CD - cdr.Result[0] = 0x08; - cdr.Result[1] = 0x10; - + if (stat.Type == 2) + cdr.Result[1] |= 0x10; + if (CdromId[0] == '\0') cdr.Result[1] |= 0x80; - } - else { - // Data CD - if (CdromId[0] == '\0') { - cdr.Result[0] = 0x00; - cdr.Result[1] = 0x80; - } - else { - cdr.Result[0] = 0x08; - cdr.Result[1] = 0x00; - } - } } + cdr.Result[0] |= (cdr.Result[1] >> 4) & 0x08; - cdr.Result[2] = 0x00; - cdr.Result[3] = 0x00; strncpy((char *)&cdr.Result[4], "PCSX", 4); cdr.Stat = Complete; break; @@ -1009,7 +989,7 @@ void cdrInterrupt() { cdr.StatP |= STATUS_ROTATING; cdr.Result[0] = cdr.StatP; cdr.Stat = Acknowledge; - AddIrqQueue(CdlReadToc + 0x20, 0x800); + AddIrqQueue(CdlReadToc + 0x20, cdReadTime * 16); break; case CdlReadToc + 0x20: @@ -1025,8 +1005,8 @@ void cdrInterrupt() { // 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 @@ -1077,14 +1057,62 @@ void cdrInterrupt() { setIrq(); #ifdef CDR_LOG_CMD_IRQ - SysPrintf("cdrInterrupt() Log: CDR Interrupt IRQ %d %02x: ", - cdr.Stat != NoIntr && cdr.Reg2 != 0x18, Irq); + SysPrintf("IRQ %d cmd %02x stat %02x: ", + !!(cdr.Stat & cdr.Reg2), Irq, cdr.Stat); for (i = 0; i < cdr.ResultC; i++) SysPrintf("%02x ", cdr.Result[i]); SysPrintf("\n"); #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; @@ -1104,7 +1132,7 @@ void cdrReadInterrupt() { cdr.Result[0] = cdr.StatP; cdr.Seeked = SEEK_DONE; - ReadTrack(cdr.SetSector, 0); + ReadTrack(cdr.SetSector); buf = CDR_getBuffer(); if (buf == NULL) @@ -1132,40 +1160,14 @@ void cdrReadInterrupt() { cdr.Channel = cdr.Transfer[4 + 1]; } - if ((cdr.Transfer[4 + 2] & 0x4) && + if((cdr.Transfer[4 + 2] & 0x4) && (cdr.Transfer[4 + 1] == cdr.Channel) && - (cdr.Transfer[4 + 0] == cdr.File)) { + (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; - -#if 0 - // Crash Team Racing: music, speech - // - done using cdda decoded buffer (spu irq) - // - don't do here - - // signal ADPCM data ready - setIrq(); -#endif } else cdr.FirstSector = -1; } @@ -1197,7 +1199,7 @@ void cdrReadInterrupt() { } // update for CdlGetlocP - ReadTrack(cdr.SetSector, 0); + ReadTrack(cdr.SetSector); Check_Shell(0); } @@ -1262,7 +1264,7 @@ void cdrWrite1(unsigned char rt) { case 0: break; case 3: - cdr.AttenuatorRight[1] = rt; + cdr.AttenuatorRightToRightT = rt; return; default: return; @@ -1272,7 +1274,7 @@ void cdrWrite1(unsigned char rt) { cdr.OCUP = 0; #ifdef CDR_LOG_CMD_IRQ - SysPrintf("cdrWrite1() Log: CD1 write: %x (%s)", rt, CmdName[rt]); + SysPrintf("CD1 write: %x (%s)", rt, CmdName[rt]); if (cdr.ParamC) { SysPrintf(" Param[%d] = {", cdr.ParamC); for (i = 0; i < cdr.ParamC; i++) @@ -1326,23 +1328,8 @@ void cdrWrite1(unsigned char rt) { // Vib Ribbon: try same track again StopCdda(); -#if 0 - if (!cdr.SetSector[0] & !cdr.SetSector[1] & !cdr.SetSector[2]) { - if (CDR_getTN(cdr.ResultTN) != -1) { - if (cdr.CurTrack > cdr.ResultTN[1]) - cdr.CurTrack = cdr.ResultTN[1]; - if (CDR_getTD((unsigned char)(cdr.CurTrack), cdr.ResultTD) != -1) { - int tmp = cdr.ResultTD[2]; - cdr.ResultTD[2] = cdr.ResultTD[0]; - cdr.ResultTD[0] = tmp; - if (!Config.Cdda) CDR_play(cdr.ResultTD); - } - } - } -#endif // Vib Ribbon - decoded buffer IRQ for CDDA reading // - fixes ribbon timing + music CD mode - //TODO? //CDRDBUF_INT( PSXCLK / 44100 * 0x100 ); cdr.Play = TRUE; @@ -1483,10 +1470,10 @@ void cdrWrite2(unsigned char rt) { setIrq(); return; case 2: - cdr.AttenuatorLeft[0] = rt; + cdr.AttenuatorLeftToLeftT = rt; return; case 3: - cdr.AttenuatorRight[0] = rt; + cdr.AttenuatorRightToLeftT = rt; return; } } @@ -1514,13 +1501,15 @@ void cdrWrite3(unsigned char rt) { 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; } @@ -1565,10 +1554,11 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) { // - fix boot if( cdsize == 0 ) { - switch (cdr.Mode & 0x30) { - case 0x00: cdsize = 2048; break; - case MODE_SIZE_2328: cdsize = 2328; break; + switch (cdr.Mode & (MODE_SIZE_2340|MODE_SIZE_2328)) { case MODE_SIZE_2340: cdsize = 2340; break; + case MODE_SIZE_2328: cdsize = 2328; break; + default: + case MODE_SIZE_2048: cdsize = 2048; break; } } @@ -1626,9 +1616,6 @@ void cdrDmaInterrupt() static void getCdInfo(void) { - unsigned int i, j, sector; - struct SubQ *subq; - u8 tmpp[3]; u8 tmp; CDR_getTN(cdr.ResultTN); @@ -1636,26 +1623,6 @@ static void getCdInfo(void) 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() { @@ -1663,13 +1630,15 @@ void cdrReset() { cdr.CurTrack = 1; cdr.File = 1; cdr.Channel = 1; + cdr.Reg2 = 0x1f; + cdr.Stat = NoIntr; 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(); } @@ -1699,7 +1668,7 @@ int cdrFreeze(void *f, int Mode) { // read right sub data memcpy(tmpp, cdr.Prev, 3); cdr.Prev[0]++; - ReadTrack(tmpp, 1); + ReadTrack(tmpp); if (cdr.Play) { Find_CurTrack(cdr.SetSectorPlay);