X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libpcsxcore%2Fcdrom.c;h=93b3c4facd93d12c85222f6c24c3d6bd33e6af4a;hb=66425c25db8a6e4d33488977bf745af73dbe8b39;hp=a417a5283e712996c69b14dc47feec88759940c6;hpb=0204c39a68a1fd4bf667aa8ece5a769f2983b7d0;p=pcsx_rearmed.git diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index a417a528..93b3c4fa 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -46,6 +46,7 @@ cdrStruct cdr; static unsigned char *pTransfer; +static s16 read_buf[CD_FRAMESIZE_RAW/2]; /* CD-ROM magic numbers */ #define CdlSync 0 @@ -58,7 +59,7 @@ static unsigned char *pTransfer; #define CdlStandby 7 #define CdlStop 8 #define CdlPause 9 -#define CdlInit 10 +#define CdlReset 10 #define CdlMute 11 #define CdlDemute 12 #define CdlSetfilter 13 @@ -76,19 +77,19 @@ static unsigned char *pTransfer; #define CdlTest 25 #define CdlID 26 #define CdlReadS 27 -#define CdlReset 28 +#define CdlInit 28 #define CdlGetQ 29 #define CdlReadToc 30 char *CmdName[0x100]= { "CdlSync", "CdlNop", "CdlSetloc", "CdlPlay", "CdlForward", "CdlBackward", "CdlReadN", "CdlStandby", - "CdlStop", "CdlPause", "CdlInit", "CdlMute", + "CdlStop", "CdlPause", "CdlReset", "CdlMute", "CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetmode", "CdlGetlocL", "CdlGetlocP", "CdlReadT", "CdlGetTN", "CdlGetTD", "CdlSeekL", "CdlSeekP", "CdlSetclock", "CdlGetclock", "CdlTest", "CdlID", "CdlReadS", - "CdlReset", NULL, "CDlReadToc", NULL + "CdlInit", NULL, "CDlReadToc", NULL }; unsigned char Test04[] = { 0 }; @@ -431,6 +432,10 @@ static void AddIrqQueue(unsigned short irq, unsigned long ecycle) { static void cdrPlayInterrupt_Autopause() { + u32 abs_lev_max = 0; + boolean abs_lev_chselect; + u32 i; + if ((cdr.Mode & MODE_AUTOPAUSE) && cdr.TrackChanged) { CDR_LOG( "CDDA STOP\n" ); @@ -445,11 +450,21 @@ static void cdrPlayInterrupt_Autopause() StopCdda(); } - else if (cdr.Mode & MODE_REPORT) { - + else if (((cdr.Mode & MODE_REPORT) || cdr.FastForward || cdr.FastBackward)) { + CDR_readCDDA(cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2], (u8 *)read_buf); cdr.Result[0] = cdr.StatP; cdr.Result[1] = cdr.subq.Track; cdr.Result[2] = cdr.subq.Index; + + abs_lev_chselect = cdr.subq.Absolute[1] & 0x01; + + /* 8 is a hack. For accuracy, it should be 588. */ + for (i = 0; i < 8; i++) + { + abs_lev_max = MAX_VALUE(abs_lev_max, abs(read_buf[i * 2 + abs_lev_chselect])); + } + abs_lev_max = MIN_VALUE(abs_lev_max, 32767); + abs_lev_max |= abs_lev_chselect << 15; if (cdr.subq.Absolute[2] & 0x10) { cdr.Result[3] = cdr.subq.Relative[0]; @@ -462,8 +477,8 @@ static void cdrPlayInterrupt_Autopause() cdr.Result[5] = cdr.subq.Absolute[2]; } - cdr.Result[6] = 0; - cdr.Result[7] = 0; + cdr.Result[6] = abs_lev_max >> 0; + cdr.Result[7] = abs_lev_max >> 8; // Rayman: Logo freeze (resultready + dataready) cdr.ResultReady = 1; @@ -490,12 +505,14 @@ void cdrPlayInterrupt() cdr.Seeked = SEEK_DONE; if (cdr.Irq == 0) { cdr.Stat = Complete; + cdr.RErr = 1; setIrq(); } if (cdr.SetlocPending) { memcpy(cdr.SetSectorPlay, cdr.SetSector, 4); cdr.SetlocPending = 0; + cdr.m_locationChanged = TRUE; } Find_CurTrack(cdr.SetSectorPlay); ReadTrack(cdr.SetSectorPlay); @@ -516,6 +533,12 @@ void cdrPlayInterrupt() cdrPlayInterrupt_Autopause(); if (!cdr.Play) return; + + if (CDR_readCDDA && !cdr.Muted && cdr.Mode & MODE_REPORT) { + cdrAttenuate(read_buf, CD_FRAMESIZE_RAW / 4, 1); + if (SPU_playCDDAchannel) + SPU_playCDDAchannel(read_buf, CD_FRAMESIZE_RAW); + } cdr.SetSectorPlay[2]++; if (cdr.SetSectorPlay[2] == 75) { @@ -527,7 +550,15 @@ void cdrPlayInterrupt() } } - CDRMISC_INT(cdReadTime); + if (cdr.m_locationChanged) + { + CDRMISC_INT(cdReadTime * 30); + cdr.m_locationChanged = FALSE; + } + else + { + CDRMISC_INT(cdReadTime); + } // update for CdlGetlocP/autopause generate_subq(cdr.SetSectorPlay); @@ -539,6 +570,7 @@ void cdrInterrupt() { int start_rotating = 0; int error = 0; int delay; + unsigned int seekTime = 0; // Reschedule IRQ if (cdr.Stat) { @@ -581,13 +613,16 @@ void cdrInterrupt() { do_CdlPlay: case CdlPlay: StopCdda(); - if (cdr.Seeked == SEEK_PENDING) { - // XXX: wrong, should seek instead.. - cdr.Seeked = SEEK_DONE; - } + /* It would set it to SEEK_DONE*/ + cdr.Seeked = SEEK_PENDING; + + cdr.FastBackward = 0; + cdr.FastForward = 0; + if (cdr.SetlocPending) { memcpy(cdr.SetSectorPlay, cdr.SetSector, 4); cdr.SetlocPending = 0; + cdr.m_locationChanged = TRUE; } // BIOS CD Player @@ -628,7 +663,7 @@ void cdrInterrupt() { cdr.TrackChanged = FALSE; if (!Config.Cdda) - CDR_play(cdr.SetSectorPlay); + CDR_play(); // Vib Ribbon: gameplay checks flag cdr.StatP &= ~STATUS_SEEK; @@ -646,11 +681,9 @@ void cdrInterrupt() { case CdlForward: // TODO: error 80 if stopped cdr.Stat = Complete; - + cdr.RErr = 1; // GameShark CD Player: Calls 2x + Play 2x - if( cdr.FastForward == 0 ) cdr.FastForward = 2; - else cdr.FastForward++; - + cdr.FastForward = 1; cdr.FastBackward = 0; break; @@ -658,9 +691,7 @@ void cdrInterrupt() { cdr.Stat = Complete; // GameShark CD Player: Calls 2x + Play 2x - if( cdr.FastBackward == 0 ) cdr.FastBackward = 2; - else cdr.FastBackward++; - + cdr.FastBackward =1; cdr.FastForward = 0; break; @@ -675,6 +706,7 @@ void cdrInterrupt() { case CdlStandby + 0x100: cdr.Stat = Complete; + cdr.RErr = 1; break; case CdlStop: @@ -702,6 +734,7 @@ void cdrInterrupt() { cdr.StatP &= ~STATUS_ROTATING; cdr.Result[0] = cdr.StatP; cdr.Stat = Complete; + cdr.RErr = 1; break; case CdlPause: @@ -723,16 +756,20 @@ void cdrInterrupt() { cdr.StatP &= ~STATUS_READ; cdr.Result[0] = cdr.StatP; cdr.Stat = Complete; + cdr.RErr = 1; break; - case CdlInit: - AddIrqQueue(CdlInit + 0x100, cdReadTime * 6); + case CdlReset: + cdr.Muted = FALSE; + cdr.Mode = 0x20; /* Needed for This is Football 2, Pooh's Party and possibly others. */ + AddIrqQueue(CdlReset + 0x100, 4100000); no_busy_error = 1; start_rotating = 1; break; - case CdlInit + 0x100: + case CdlReset + 0x100: cdr.Stat = Complete; + cdr.RErr = 1; break; case CdlMute: @@ -783,6 +820,7 @@ void cdrInterrupt() { case CdlReadT + 0x100: cdr.Stat = Complete; + cdr.RErr = 1; break; case CdlGetTN: @@ -880,9 +918,10 @@ void cdrInterrupt() { /* This adds the string "PCSX" in Playstation bios boot screen */ memcpy((char *)&cdr.Result[4], "PCSX", 4); cdr.Stat = Complete; + cdr.RErr = 1; break; - case CdlReset: + case CdlInit: // yes, it really sets STATUS_SHELLOPEN cdr.StatP |= STATUS_SHELLOPEN; cdr.DriveState = DRIVESTATE_RESCAN_CD; @@ -904,14 +943,33 @@ void cdrInterrupt() { case CdlReadToc + 0x100: cdr.Stat = Complete; + cdr.RErr = 1; no_busy_error = 1; break; case CdlReadN: case CdlReadS: if (cdr.SetlocPending) { + seekTime = abs(msf2sec(cdr.SetSectorPlay) - msf2sec(cdr.SetSector)) * (cdReadTime / 200); + /* + * Gameblabla : + * It was originally set to 1000000 for Driver, however it is not high enough for Worms Pinball + * and was unreliable for that game. + * I also tested it against Mednafen and Driver's titlescreen music starts 25 frames later, not immediatly. + * + * Obviously, this isn't perfect but right now, it should be a bit better. + * Games to test this against if you change that setting : + * - Driver (titlescreen music delay and retry mission) + * - Worms Pinball (Will either not boot or crash in the memory card screen) + * - Viewpoint (short pauses if the delay in the ingame music is too long) + * + * It seems that 3386880 * 5 is too much for Driver's titlescreen and it starts skipping. + * However, 1000000 is not enough for Worms Pinball to reliably boot. + */ + if(seekTime > 3386880 * 2) seekTime = 3386880 * 2; memcpy(cdr.SetSectorPlay, cdr.SetSector, 4); cdr.SetlocPending = 0; + cdr.m_locationChanged = TRUE; } Find_CurTrack(cdr.SetSectorPlay); @@ -941,21 +999,26 @@ void cdrInterrupt() { C-12 - Final Resistance - doesn't like seek */ - if (cdr.Seeked != SEEK_DONE) { - cdr.StatP |= STATUS_SEEK; - cdr.StatP &= ~STATUS_READ; - - // Crusaders of Might and Magic - use short time - // - fix cutscene speech (startup) - - // ??? - use more accurate seek time later - CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1); - } else { - cdr.StatP |= STATUS_READ; - cdr.StatP &= ~STATUS_SEEK; - - CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime * 1); - } + /* + By nicolasnoble from PCSX Redux : + "It LOOKS like this logic is wrong, therefore disabling it with `&& false` for now. + For "PoPoLoCrois Monogatari II", the game logic will soft lock and will never issue GetLocP to detect + the end of its XA streams, as it seems to assume ReadS will not return a status byte with the SEEK + flag set. I think the reasonning is that since it's invalid to call GetLocP while seeking, the game + tries to protect itself against errors by preventing from issuing a GetLocP while it knows the + last status was "seek". But this makes the logic just softlock as it'll never get a notification + about the fact the drive is done seeking and the read actually started. + In other words, this state machine here is probably wrong in assuming the response to ReadS/ReadN is + done right away. It's rather when it's done seeking, and the read has actually started. This probably + requires a bit more work to make sure seek delays are processed properly. + Checked with a few games, this seems to work fine." + + Gameblabla additional notes : + This still needs the "+ seekTime" that PCSX Redux doesn't have for the Driver "retry" mission error. + */ + cdr.StatP |= STATUS_READ; + cdr.StatP &= ~STATUS_SEEK; + CDREAD_INT(((cdr.Mode & 0x80) ? (cdReadTime) : cdReadTime * 2) + seekTime); cdr.Result[0] = cdr.StatP; start_rotating = 1; @@ -1079,9 +1142,9 @@ void cdrReadInterrupt() { buf = CDR_getBuffer(); if (buf == NULL) - cdr.RErr = -1; + cdr.RErr = 0; - if (cdr.RErr == -1) { + if (cdr.RErr == 0) { CDR_LOG_I("cdrReadInterrupt() Log: err\n"); memset(cdr.Transfer, 0, DATA_SIZE); cdr.Stat = DiskError; @@ -1103,9 +1166,14 @@ void cdrReadInterrupt() { cdr.Channel = cdr.Transfer[4 + 1]; } + /* Gameblabla + * Skips playing on channel 255. + * Fixes missing audio in Blue's Clues : Blue's Big Musical. (Should also fix Taxi 2) + * TODO : Check if this is the proper behaviour. + * */ if((cdr.Transfer[4 + 2] & 0x4) && (cdr.Transfer[4 + 1] == cdr.Channel) && - (cdr.Transfer[4 + 0] == cdr.File)) { + (cdr.Transfer[4 + 0] == cdr.File) && cdr.Channel != 255) { int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector); if (!ret) { cdrAttenuate(cdr.Xa.pcm, cdr.Xa.nsamples, cdr.Xa.stereo); @@ -1128,7 +1196,13 @@ void cdrReadInterrupt() { cdr.Readed = 0; - CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime); + uint32_t delay = (cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime; + if (cdr.m_locationChanged) { + CDREAD_INT(delay * 30); + cdr.m_locationChanged = FALSE; + } else { + CDREAD_INT(delay); + } /* Croc 2: $40 - only FORM1 (*) @@ -1253,8 +1327,8 @@ void cdrWrite1(unsigned char rt) { StopReading(); break; - case CdlReset: case CdlInit: + case CdlReset: cdr.Seeked = SEEK_DONE; StopCdda(); StopReading(); @@ -1466,6 +1540,8 @@ void cdrReset() { cdr.DriveState = DRIVESTATE_STANDBY; cdr.StatP = STATUS_ROTATING; pTransfer = cdr.Transfer; + cdr.SetlocPending = 0; + cdr.m_locationChanged = FALSE; // BIOS player - default values cdr.AttenuatorLeftToLeft = 0x80; @@ -1511,7 +1587,7 @@ int cdrFreeze(void *f, int Mode) { Find_CurTrack(cdr.SetSectorPlay); if (!Config.Cdda) - CDR_play(cdr.SetSectorPlay); + CDR_play(); } if ((cdr.freeze_ver & 0xffffff00) != 0x63647200) {