X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=libpcsxcore%2Fcdrom.c;h=60f03e745b0242ce695c5aa3919c23ae8b6dfb9b;hp=1aa958b0642ae99e301d487e7d0f138ee930b190;hb=f29fbd5358e28135d389e2218da7c90f8b94b983;hpb=8e1040b6a82ee1802fda83d4de84290a02656cc0 diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index 1aa958b0..60f03e74 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -120,13 +120,20 @@ unsigned char Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; // so (PSXCLK / 75) = cdr read time (linuzappz) #define cdReadTime (PSXCLK / 75) +// for cdr.Seeked +enum seeked_state { + SEEK_PENDING = 0, + SEEK_DONE = 1, + SEEK_DOING_CMD = 2, +}; + static struct CdrStat stat; -static unsigned int msf2sec(char *msf) { +static unsigned int msf2sec(u8 *msf) { return ((msf[0] * 60 + msf[1]) * 75) + msf[2]; } -static void sec2msf(unsigned int s, char *msf) { +static void sec2msf(unsigned int s, u8 *msf) { msf[0] = s / 75 / 60; s = s - msf[0] * 75 * 60; msf[1] = s / 75; @@ -134,7 +141,7 @@ static void sec2msf(unsigned int s, char *msf) { msf[2] = s; } - +// cdrInterrupt #define CDR_INT(eCycle) { \ psxRegs.interrupt |= (1 << PSXINT_CDR); \ psxRegs.intCycle[PSXINT_CDR].cycle = eCycle; \ @@ -142,6 +149,7 @@ static void sec2msf(unsigned int s, char *msf) { new_dyna_set_event(PSXINT_CDR, eCycle); \ } +// cdrReadInterrupt #define CDREAD_INT(eCycle) { \ psxRegs.interrupt |= (1 << PSXINT_CDREAD); \ psxRegs.intCycle[PSXINT_CDREAD].cycle = eCycle; \ @@ -149,6 +157,7 @@ static void sec2msf(unsigned int s, char *msf) { new_dyna_set_event(PSXINT_CDREAD, eCycle); \ } +// cdrLidSeekInterrupt #define CDRLID_INT(eCycle) { \ psxRegs.interrupt |= (1 << PSXINT_CDRLID); \ psxRegs.intCycle[PSXINT_CDRLID].cycle = eCycle; \ @@ -156,7 +165,8 @@ static void sec2msf(unsigned int s, char *msf) { new_dyna_set_event(PSXINT_CDRLID, eCycle); \ } -#define CDRPLAY_INT(eCycle) { \ +// cdrPlayInterrupt +#define CDRMISC_INT(eCycle) { \ psxRegs.interrupt |= (1 << PSXINT_CDRPLAY); \ psxRegs.intCycle[PSXINT_CDRPLAY].cycle = eCycle; \ psxRegs.intCycle[PSXINT_CDRPLAY].sCycle = psxRegs.cycle; \ @@ -252,7 +262,6 @@ void cdrLidSeekInterrupt() } } - static void Check_Shell( int Irq ) { // check case open/close @@ -411,12 +420,13 @@ static void ReadTrack( u8 *time ) { } -void AddIrqQueue(unsigned char irq, unsigned long ecycle) { +static void AddIrqQueue(unsigned char irq, unsigned long ecycle) { + //if (cdr.Irq != 0 && cdr.Irq != 0xff) + // printf("cdr: override cmd %02x -> %02x\n", cdr.Irq, irq); + cdr.Irq = irq; cdr.eCycle = ecycle; - // Doom: Force rescheduling - // - Fixes boot CDR_INT(ecycle); } @@ -557,6 +567,8 @@ static void cdrPlayInterrupt_Autopause() Tomb Raider 1 ($7) */ + // .. + 1 is probably wrong, but deals with corrupted subq + good checksum + // (how does real thing handle those?) if( cdr.CurTrack + 1 == btoi( subq->TrackNumber ) ) track_changed = 1; } else { @@ -586,13 +598,14 @@ static void cdrPlayInterrupt_Autopause() StopCdda(); } - if (cdr.Mode & MODE_REPORT) { + else if (cdr.Mode & MODE_REPORT) { 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 ); + // breaks when .sub doesn't have index 0 for some reason (bad rip?) + //cdr.CurTrack = btoi( subq->TrackNumber ); if (subq->AbsoluteAddress[2] & 0xf) return; @@ -633,15 +646,40 @@ static void cdrPlayInterrupt_Autopause() } } +// also handles seek void cdrPlayInterrupt() { - if( !cdr.Play ) return; + if (cdr.Seeked == SEEK_DOING_CMD) { + SetResultSize(1); + cdr.StatP |= STATUS_ROTATING; + cdr.StatP &= ~STATUS_SEEK; + cdr.Result[0] = cdr.StatP; + if (cdr.Irq == 0 || cdr.Irq == 0xff) { + cdr.Stat = Complete; + if (cdr.Stat != NoIntr) + psxHu32ref(0x1070) |= SWAP32(0x4); + } + + cdr.Seeked = SEEK_PENDING; + CDRMISC_INT(cdReadTime * 20); // ??? + return; + } + else if (cdr.Seeked == SEEK_PENDING) { + cdr.Seeked = SEEK_DONE; + if (!cdr.Play && !cdr.Reading) { + memcpy(cdr.SetSectorPlay, cdr.SetSector, 4); + Find_CurTrack(); + ReadTrack(cdr.SetSector); + } + } + + 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 ); + CDRMISC_INT( cdReadTime ); if (!cdr.Irq && !cdr.Stat && (cdr.Mode & MODE_CDDA) && (cdr.Mode & (MODE_AUTOPAUSE|MODE_REPORT))) cdrPlayInterrupt_Autopause(); @@ -700,9 +738,10 @@ void cdrInterrupt() { case CdlPlay: fake_subq_change = 0; - if( cdr.Seeked == FALSE ) { + if (cdr.Seeked == SEEK_PENDING) { + // XXX: wrong, should seek instead.. memcpy( cdr.SetSectorPlay, cdr.SetSector, 4 ); - cdr.Seeked = TRUE; + cdr.Seeked = SEEK_DONE; } /* @@ -783,7 +822,7 @@ void cdrInterrupt() { cdr.SetSectorPlay[2] = cdr.ResultTD[0]; // reset data - Set_Track(); + //Set_Track(); Find_CurTrack(); ReadTrack( cdr.SetSectorPlay ); @@ -811,7 +850,7 @@ void cdrInterrupt() { // BIOS player - set flag again cdr.Play = TRUE; - CDRPLAY_INT( cdReadTime ); + CDRMISC_INT( cdReadTime ); break; case CdlForward: @@ -962,8 +1001,9 @@ void cdrInterrupt() { subq = (struct SubQ *)CDR_getBufferSub(); if (subq != NULL) { - // update subq - ReadTrack( cdr.SetSectorPlay ); + if( cdr.Play && (cdr.Mode & MODE_CDDA) && !(cdr.Mode & (MODE_AUTOPAUSE|MODE_REPORT)) ) + // update subq + ReadTrack( cdr.SetSectorPlay ); cdr.Result[0] = subq->TrackNumber; cdr.Result[1] = subq->IndexNumber; @@ -1043,6 +1083,7 @@ void cdrInterrupt() { break; case CdlSeekL: + case CdlSeekP: SetResultSize(1); cdr.StatP |= STATUS_ROTATING; cdr.Result[0] = cdr.StatP; @@ -1062,45 +1103,8 @@ void cdrInterrupt() { Rockman X5 = 0.5-4x - fix capcom logo */ - AddIrqQueue(CdlSeekL + 0x20, cdReadTime * 4); - break; - - case CdlSeekL + 0x20: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.StatP &= ~STATUS_SEEK; - cdr.Result[0] = cdr.StatP; - cdr.Seeked = TRUE; - cdr.Stat = Complete; - - - // Mega Man Legends 2: must update read cursor for getlocp - ReadTrack( cdr.SetSector ); - break; - - case CdlSeekP: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.Result[0] = cdr.StatP; - cdr.StatP |= STATUS_SEEK; - cdr.Stat = Acknowledge; - AddIrqQueue(CdlSeekP + 0x20, cdReadTime * 1); - break; - - case CdlSeekP + 0x20: - SetResultSize(1); - cdr.StatP |= STATUS_ROTATING; - cdr.StatP &= ~STATUS_SEEK; - cdr.Result[0] = cdr.StatP; - cdr.Stat = Complete; - cdr.Seeked = TRUE; - - // GameShark Music Player - memcpy( cdr.SetSectorPlay, cdr.SetSector, 4 ); - - // Tomb Raider 2: must update read cursor for getlocp - Find_CurTrack(); - ReadTrack( cdr.SetSectorPlay ); + CDRMISC_INT(cdr.Seeked == SEEK_DONE ? 0x800 : cdReadTime * 4); + cdr.Seeked = SEEK_DOING_CMD; break; case CdlTest: @@ -1229,17 +1233,14 @@ void cdrInterrupt() { 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) { - cdr.Seeked = TRUE; - + if (cdr.Seeked != SEEK_DONE) { cdr.StatP |= STATUS_SEEK; cdr.StatP &= ~STATUS_READ; @@ -1279,7 +1280,10 @@ void cdrInterrupt() { } #ifdef CDR_LOG - CDR_LOG("cdrInterrupt() Log: CDR Interrupt IRQ %x\n", Irq); + printf("cdrInterrupt() Log: CDR Interrupt IRQ %x: ", Irq); + for (i = 0; i < cdr.ResultC; i++) + printf("%02x ", cdr.Result[i]); + printf("\n"); #endif } @@ -1303,6 +1307,7 @@ void cdrReadInterrupt() { cdr.StatP |= STATUS_READ|STATUS_ROTATING; cdr.StatP &= ~STATUS_SEEK; cdr.Result[0] = cdr.StatP; + cdr.Seeked = SEEK_DONE; ReadTrack( cdr.SetSector ); @@ -1480,7 +1485,7 @@ unsigned char cdrRead1(void) { } void cdrWrite1(unsigned char rt) { - char set_loc[3]; + u8 set_loc[3]; int i; #ifdef CDR_LOG @@ -1533,17 +1538,14 @@ void cdrWrite1(unsigned char rt) { StopReading(); for (i = 0; i < 3; i++) set_loc[i] = btoi(cdr.Param[i]); + i = abs(msf2sec(cdr.SetSector) - msf2sec(set_loc)); if (i > 16) - cdr.Seeked = FALSE; + cdr.Seeked = SEEK_PENDING; + memcpy(cdr.SetSector, set_loc, 3); cdr.SetSector[3] = 0; - /* - if ((cdr.SetSector[0] | cdr.SetSector[1] | cdr.SetSector[2]) == 0) { - *(u32 *)cdr.SetSector = *(u32 *)cdr.SetSectorSeek; - }*/ - cdr.Ctrl |= 0x80; cdr.Stat = NoIntr; AddIrqQueue(cdr.Cmd, 0x800); @@ -1659,6 +1661,7 @@ void cdrWrite1(unsigned char rt) { case CdlReset: case CdlInit: + cdr.Seeked = SEEK_DONE; StopCdda(); StopReading(); cdr.Ctrl |= 0x80;