From 7f457614c936a6f37d12c1885bd504a7a7823690 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 28 Jan 2011 17:30:01 +0200 Subject: [PATCH] cdrom: support cdda playback cursor and autopause/report some differences from PCSX-Reloaded version --- libpcsxcore/cdrom.c | 134 +++++++++++++++++++++++++++++-- libpcsxcore/new_dynarec/emu_if.c | 2 + libpcsxcore/r3000a.c | 6 ++ libpcsxcore/r3000a.h | 1 + 4 files changed, 138 insertions(+), 5 deletions(-) diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index dbae5bc8..4ca27e22 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; \ @@ -446,7 +452,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 +535,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) { @@ -679,8 +803,7 @@ void cdrInterrupt() { // BIOS player - set flag again cdr.Play = TRUE; - // TODO? - // CDRPLAY_INT( cdReadTime ); + CDRPLAY_INT( cdReadTime ); break; case CdlForward: @@ -834,7 +957,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 # diff --git a/libpcsxcore/new_dynarec/emu_if.c b/libpcsxcore/new_dynarec/emu_if.c index bdb96755..3bfec4e7 100644 --- a/libpcsxcore/new_dynarec/emu_if.c +++ b/libpcsxcore/new_dynarec/emu_if.c @@ -63,6 +63,7 @@ static irq_func * const irq_funcs[] = { [PSXINT_GPUOTCDMA] = gpuotcInterrupt, [PSXINT_CDRDMA] = cdrDmaInterrupt, [PSXINT_CDRLID] = cdrLidSeekInterrupt, + [PSXINT_CDRPLAY] = cdrPlayInterrupt, }; /* local dupe of psxBranchTest, using event_cycles */ @@ -174,6 +175,7 @@ static void ari64_reset() printf("ari64_reset\n"); new_dyna_pcsx_mem_reset(); invalidate_all_pages(); + new_dyna_restore(); pending_exception = 1; } diff --git a/libpcsxcore/r3000a.c b/libpcsxcore/r3000a.c index ba33548d..1143b810 100644 --- a/libpcsxcore/r3000a.c +++ b/libpcsxcore/r3000a.c @@ -169,6 +169,12 @@ void psxBranchTest() { cdrDmaInterrupt(); } } + if (psxRegs.interrupt & (1 << PSXINT_CDRPLAY)) { // cdr play timing + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDRPLAY].sCycle) >= psxRegs.intCycle[PSXINT_CDRPLAY].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_CDRPLAY); + cdrPlayInterrupt(); + } + } if (psxRegs.interrupt & (1 << PSXINT_CDRLID)) { // cdr lid states if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_CDRLID].sCycle) >= psxRegs.intCycle[PSXINT_CDRLID].cycle) { psxRegs.interrupt &= ~(1 << PSXINT_CDRLID); diff --git a/libpcsxcore/r3000a.h b/libpcsxcore/r3000a.h index dfce1731..aced3818 100644 --- a/libpcsxcore/r3000a.h +++ b/libpcsxcore/r3000a.h @@ -159,6 +159,7 @@ enum { PSXINT_NEWDRC_CHECK, DUMMY2, PSXINT_CDRLID, + PSXINT_CDRPLAY, PSXINT_COUNT }; -- 2.39.2