X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=libpcsxcore%2Fcdrom.c;h=d9a3bb37cd05372f3f2369557b55c0acf3495051;hp=fff316065484a3e969ae8613b060206754ba92df;hb=42f3c5125fcb99e1445dfb7ca3d1b21330cde414;hpb=9f8b032dc5074e29f2e93ce06651f6da3bb70a86 diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index fff31606..d9a3bb37 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -120,7 +120,6 @@ unsigned char Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; #define cdReadTime (PSXCLK / 75) static struct CdrStat stat; -static struct SubQ *subq; static unsigned int msf2sec(char *msf) { return ((msf[0] * 60 + msf[1]) * 75) + msf[2]; @@ -156,6 +155,13 @@ static void sec2msf(unsigned int s, char *msf) { new_dyna_set_event(PSXINT_CDRLID, eCycle); \ } +#define CDRPLAY_INT(eCycle) { \ + psxRegs.interrupt |= (1 << PSXINT_CDRPLAY); \ + psxRegs.intCycle[PSXINT_CDRPLAY].cycle = eCycle; \ + psxRegs.intCycle[PSXINT_CDRPLAY].sCycle = psxRegs.cycle; \ + new_dyna_set_event(PSXINT_CDRPLAY, eCycle); \ +} + #define StartReading(type, eCycle) { \ cdr.Reading = type; \ cdr.FirstSector = 1; \ @@ -263,11 +269,12 @@ static void Check_Shell( int Irq ) i = stat.Status; if (CDR_getStatus(&stat) != -1) { - if (stat.Type == 0xff) - cdr.Stat = DiskError; + // BIOS hangs + BIOS error messages + //if (stat.Type == 0xff) + //cdr.Stat = DiskError; // case now open - else if (stat.Status & STATUS_SHELLOPEN) + if (stat.Status & STATUS_SHELLOPEN) { // Vib Ribbon: pre-CD swap StopCdda(); @@ -446,7 +453,7 @@ void Set_Track() static u8 fake_subq_local[3], fake_subq_real[3], fake_subq_index, fake_subq_change; -void Create_Fake_Subq() +static void Create_Fake_Subq() { u8 temp_cur[3], temp_next[3], temp_start[3], pregap; int diff; @@ -529,9 +536,127 @@ void Create_Fake_Subq() } +static void cdrPlayInterrupt_Autopause() +{ + struct SubQ *subq = (struct SubQ *)CDR_getBufferSub(); + if (subq != NULL ) { +#ifdef CDR_LOG + CDR_LOG( "CDDA SUB - %X:%X:%X\n", + subq->AbsoluteAddress[0], subq->AbsoluteAddress[1], subq->AbsoluteAddress[2] ); +#endif + + /* + CDDA Autopause + + Silhouette Mirage ($3) + Tomb Raider 1 ($7) + */ + + if( cdr.CurTrack >= btoi( subq->TrackNumber ) ) + return; + } else { + Create_Fake_Subq(); +#ifdef CDR_LOG___0 + CDR_LOG( "CDDA FAKE SUB - %d:%d:%d\n", + fake_subq_real[0], fake_subq_real[1], fake_subq_real[2] ); +#endif + + if( !fake_subq_change ) + return; + + fake_subq_change = 0; + } + + if (cdr.Mode & MODE_AUTOPAUSE) { +#ifdef CDR_LOG + CDR_LOG( "CDDA STOP\n" ); +#endif + + // Magic the Gathering + // - looping territory cdda + + // ...? + //cdr.ResultReady = 1; + //cdr.Stat = DataReady; + cdr.Stat = DataEnd; + psxHu32ref(0x1070) |= SWAP32((u32)0x4); + + StopCdda(); + } + if (cdr.Mode & MODE_REPORT) { + // rearmed note: PCSX-Reloaded does this for every sector, + // but we try to get away with only track change here. + memset( cdr.Result, 0, 8 ); + cdr.Result[0] |= 0x10; + + if (subq != NULL) { +#ifdef CDR_LOG + CDR_LOG( "REPPLAY SUB - %X:%X:%X\n", + subq->AbsoluteAddress[0], subq->AbsoluteAddress[1], subq->AbsoluteAddress[2] ); +#endif + cdr.CurTrack = btoi( subq->TrackNumber ); + + // 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 { +#ifdef CDR_LOG___0 + CDR_LOG( "REPPLAY FAKE - %d:%d:%d\n", + fake_subq_real[0], fake_subq_real[1], fake_subq_real[2] ); +#endif + + // 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); + } +} + +void cdrPlayInterrupt() +{ + if( !cdr.Play ) return; + +#ifdef CDR_LOG + CDR_LOG( "CDDA - %d:%d:%d\n", + cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] ); +#endif + CDRPLAY_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); +} + void cdrInterrupt() { int i; unsigned char Irq = cdr.Irq; + struct SubQ *subq; // Reschedule IRQ if (cdr.Stat) { @@ -584,11 +709,12 @@ void cdrInterrupt() { Wild 9: skip PREGAP + starting accurate SubQ - plays tracks without retry play */ + /* unneeded with correct cdriso? Set_Track(); + */ Find_CurTrack(); ReadTrack( cdr.SetSectorPlay ); - // GameShark CD Player: Calls 2x + Play 2x if( cdr.FastBackward || cdr.FastForward ) { if( cdr.FastForward ) cdr.FastForward--; @@ -679,8 +805,7 @@ void cdrInterrupt() { // BIOS player - set flag again cdr.Play = TRUE; - // TODO? - // CDRPLAY_INT( cdReadTime ); + CDRPLAY_INT( cdReadTime ); break; case CdlForward: @@ -737,7 +862,17 @@ void cdrInterrupt() { cdr.Result[0] = cdr.StatP; cdr.Stat = Acknowledge; - AddIrqQueue(CdlPause + 0x20, 0x800); + /* + Gundam Battle Assault 2: much slower (*) + - Fixes boot, gameplay + + Hokuto no Ken 2: slower + - Fixes intro + subtitles + + InuYasha - Feudal Fairy Tale: slower + - Fixes battles + */ + AddIrqQueue(CdlPause + 0x20, cdReadTime * 3); cdr.Ctrl |= 0x80; break; @@ -834,7 +969,8 @@ void cdrInterrupt() { } } } else { - if( cdr.Play == FALSE ) Create_Fake_Subq(); + if( cdr.Play == FALSE || !(cdr.Mode & MODE_CDDA) || !(cdr.Mode & (MODE_AUTOPAUSE|MODE_REPORT)) ) + Create_Fake_Subq(); // track # / index # @@ -853,10 +989,9 @@ void cdrInterrupt() { } // redump.org - wipe time - /*if( !cdr.Play && CheckSBI(cdr.Result+5) ) { + if( !cdr.Play && CheckSBI(cdr.Result+5) ) { memset( cdr.Result+2, 0, 6 ); } - */ cdr.Stat = Acknowledge; break; @@ -1082,13 +1217,15 @@ void cdrInterrupt() { // - fixes cutscene speech { u8 *buf = CDR_getBuffer(); - memcpy(cdr.Transfer, buf, 8); + if (buf != NULL) + memcpy(cdr.Transfer, buf, 8); } /* Duke Nukem: Land of the Babes - seek then delay read for one frame - fixes cutscenes + C-12 - Final Resistance - doesn't like seek */ if (!cdr.Seeked) { @@ -1193,14 +1330,34 @@ void cdrReadInterrupt() { 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]; + } + } + 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 psxHu32ref(0x1070) |= SWAP32((u32)0x200); +#endif } else cdr.FirstSector = -1; } @@ -1317,6 +1474,7 @@ unsigned char cdrRead1(void) { } void cdrWrite1(unsigned char rt) { + char set_loc[3]; int i; #ifdef CDR_LOG @@ -1326,7 +1484,7 @@ void cdrWrite1(unsigned char rt) { // Tekken: CDXA fade-out if( (cdr.Ctrl & 3) == 3 ) { - //cdr.AttenuatorRight[0] = rt; + cdr.AttenuatorRight[0] = rt; } @@ -1365,9 +1523,12 @@ void cdrWrite1(unsigned char rt) { case CdlSetloc: StopReading(); - cdr.Seeked = FALSE; for (i = 0; i < 3; i++) - cdr.SetSector[i] = btoi(cdr.Param[i]); + set_loc[i] = btoi(cdr.Param[i]); + i = abs(msf2sec(cdr.SetSector) - msf2sec(set_loc)); + if (i > 16) + cdr.Seeked = FALSE; + memcpy(cdr.SetSector, set_loc, 3); cdr.SetSector[3] = 0; /* @@ -1477,31 +1638,15 @@ void cdrWrite1(unsigned char rt) { /* GameShark CD Player: save time for resume - Twisted Metal - World Tour: don't save times for DATA reads - - Only get 1 chance to do this right - */ - if( cdr.Play && CDR_getStatus(&stat) != -1 ) { - cdr.SetSectorPlay[0] = stat.Time[0]; - cdr.SetSectorPlay[1] = stat.Time[1]; - cdr.SetSectorPlay[2] = stat.Time[2]; - } + Twisted Metal - World Tour: don't mix Setloc / CdlPlay cursors + */ StopCdda(); StopReading(); cdr.Ctrl |= 0x80; cdr.Stat = NoIntr; - /* - Gundam Battle Assault 2: much slower (*) - - Fixes boot, gameplay - - Hokuto no Ken 2: slower - - Fixes intro + subtitles - - InuYasha - Feudal Fairy Tale: slower - - Fixes battles - */ - AddIrqQueue(cdr.Cmd, cdReadTime * 3); + AddIrqQueue(cdr.Cmd, 0x800); break; case CdlReset: @@ -1583,7 +1728,11 @@ void cdrWrite1(unsigned char rt) { //AddIrqQueue(cdr.Cmd, 0x28); // Tomb Raider 2 - cdda - AddIrqQueue(cdr.Cmd, 0x40); + //AddIrqQueue(cdr.Cmd, 0x40); + + // rearmed: the above works in pcsxr-svn, but breaks here + // (TOCA world touring cars), perhaps some other code is not merged yet + AddIrqQueue(cdr.Cmd, 0x1000); break; case CdlGetTN: @@ -1690,10 +1839,10 @@ void cdrWrite2(unsigned char rt) { // Tekken: CDXA fade-out if( (cdr.Ctrl & 3) == 2 ) { - //cdr.AttenuatorLeft[0] = rt; + cdr.AttenuatorLeft[0] = rt; } else if( (cdr.Ctrl & 3) == 3 ) { - //cdr.AttenuatorRight[1] = rt; + cdr.AttenuatorRight[1] = rt; } @@ -1735,7 +1884,7 @@ void cdrWrite3(unsigned char rt) { #ifdef CDR_LOG CDR_LOG("cdrWrite3() Log: CD3 write: %x\n", rt); #endif -/* + // Tekken: CDXA fade-out if( (cdr.Ctrl & 3) == 2 ) { cdr.AttenuatorLeft[1] = rt; @@ -1747,7 +1896,7 @@ void cdrWrite3(unsigned char rt) { cdr.AttenuatorRight[0], cdr.AttenuatorRight[1] ); #endif } -*/ + // GameShark CDX CD Player: Irq timing mania if( rt == 0 && @@ -1771,8 +1920,18 @@ void cdrWrite3(unsigned char rt) { return; } + // XA streaming - incorrect timing because of this reschedule + // - Final Fantasy Tactics + // - various other games + if (cdr.Reading && !cdr.ResultReady) { - CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime); + int left = psxRegs.intCycle[PSXINT_CDREAD].sCycle + psxRegs.intCycle[PSXINT_CDREAD].cycle - psxRegs.cycle; + int time = (cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime; + if (Config.CdrReschedule != 2) + if (left < time / 2 || Config.CdrReschedule) { // rearmed guesswork hack + //printf("-- resched %d -> %d\n", left, time); + CDREAD_INT(time); + } } return; @@ -1800,6 +1959,7 @@ void cdrWrite3(unsigned char rt) { void psxDma3(u32 madr, u32 bcr, u32 chcr) { u32 cdsize; + int size; u8 *ptr; #ifdef CDR_LOG @@ -1844,15 +2004,12 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) { - CdlPlay - Spams DMA3 and gets buffer overrun */ - - if( (cdr.pTransfer-cdr.Transfer) + cdsize > 2352 ) - { - // avoid crash - probably should wrap here - //memcpy(ptr, cdr.pTransfer, cdsize); - } - else + size = CD_FRAMESIZE_RAW - (cdr.pTransfer - cdr.Transfer); + if (size > cdsize) + size = cdsize; + if (size > 0) { - memcpy(ptr, cdr.pTransfer, cdsize); + memcpy(ptr, cdr.pTransfer, size); } psxCpu->Clear(madr, cdsize / 4); @@ -1881,8 +2038,11 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) { void cdrDmaInterrupt() { - HW_DMA3_CHCR &= SWAP32(~0x01000000); - DMA_INTERRUPT(3); + if (HW_DMA3_CHCR & SWAP32(0x01000000)) + { + HW_DMA3_CHCR &= SWAP32(~0x01000000); + DMA_INTERRUPT(3); + } } void cdrReset() { @@ -1890,6 +2050,12 @@ void cdrReset() { cdr.CurTrack = 1; cdr.File = 1; cdr.Channel = 1; + + // BIOS player - default values + cdr.AttenuatorLeft[0] = 0x80; + cdr.AttenuatorLeft[1] = 0x00; + cdr.AttenuatorRight[0] = 0x80; + cdr.AttenuatorRight[1] = 0x00; } int cdrFreeze(gzFile f, int Mode) { @@ -1907,9 +2073,13 @@ int cdrFreeze(gzFile f, int Mode) { gzfreeze(&tmp, sizeof(tmp)); - if (Mode == 0) + if (Mode == 0) { cdr.pTransfer = cdr.Transfer + tmp; + if (cdr.Play && !Config.Cdda) + CDR_play(cdr.SetSectorPlay); + } + return 0; }