cdrStruct cdr;
static unsigned char *pTransfer;
+static s16 read_buf[CD_FRAMESIZE_RAW/2];
/* CD-ROM magic numbers */
#define CdlSync 0
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" );
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];
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;
cdr.Seeked = SEEK_DONE;
if (cdr.Irq == 0) {
cdr.Stat = Complete;
+ cdr.RErr = 1;
setIrq();
}
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) {
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.TrackChanged = FALSE;
if (!Config.Cdda)
- CDR_play(cdr.SetSectorPlay);
+ CDR_play();
// Vib Ribbon: gameplay checks flag
cdr.StatP &= ~STATUS_SEEK;
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;
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;
case CdlStandby + 0x100:
cdr.Stat = Complete;
+ cdr.RErr = 1;
break;
case CdlStop:
cdr.StatP &= ~STATUS_ROTATING;
cdr.Result[0] = cdr.StatP;
cdr.Stat = Complete;
+ cdr.RErr = 1;
break;
case CdlPause:
cdr.StatP &= ~STATUS_READ;
cdr.Result[0] = cdr.StatP;
cdr.Stat = Complete;
+ cdr.RErr = 1;
break;
case CdlReset:
case CdlReset + 0x100:
cdr.Stat = Complete;
+ cdr.RErr = 1;
break;
case CdlMute:
case CdlReadT + 0x100:
cdr.Stat = Complete;
+ cdr.RErr = 1;
break;
case CdlGetTN:
/* 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 CdlInit:
case CdlReadToc + 0x100:
cdr.Stat = Complete;
+ cdr.RErr = 1;
no_busy_error = 1;
break;
case CdlReadS:
if (cdr.SetlocPending) {
seekTime = abs(msf2sec(cdr.SetSectorPlay) - msf2sec(cdr.SetSector)) * (cdReadTime / 200);
- if(seekTime > 1000000) seekTime = 1000000;
+ /*
+ * 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;
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) + seekTime);
- } 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;
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;
Find_CurTrack(cdr.SetSectorPlay);
if (!Config.Cdda)
- CDR_play(cdr.SetSectorPlay);
+ CDR_play();
}
if ((cdr.freeze_ver & 0xffffff00) != 0x63647200) {