new_dyna_set_event(PSXINT_CDR, eCycle); \
}
-// cdrReadInterrupt
-#define CDREAD_INT(eCycle) { \
+// cdrPlaySeekReadInterrupt
+#define CDRPLAYSEEKREAD_INT(eCycle, isFirst) { \
+ u32 e_ = eCycle; \
psxRegs.interrupt |= (1 << PSXINT_CDREAD); \
- psxRegs.intCycle[PSXINT_CDREAD].cycle = eCycle; \
- psxRegs.intCycle[PSXINT_CDREAD].sCycle = psxRegs.cycle; \
- new_dyna_set_event(PSXINT_CDREAD, eCycle); \
+ if (isFirst) \
+ psxRegs.intCycle[PSXINT_CDREAD].sCycle = psxRegs.cycle; \
+ else \
+ psxRegs.intCycle[PSXINT_CDREAD].sCycle += psxRegs.intCycle[PSXINT_CDREAD].cycle; \
+ psxRegs.intCycle[PSXINT_CDREAD].cycle = e_; \
+ new_dyna_set_event_abs(PSXINT_CDREAD, psxRegs.intCycle[PSXINT_CDREAD].sCycle + e_); \
}
// cdrLidSeekInterrupt
new_dyna_set_event(PSXINT_CDRLID, eCycle); \
}
-// cdrPlayInterrupt
-#define CDRSEEKPLAY_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 StopReading() { \
cdr.Reading = 0; \
psxRegs.interrupt &= ~(1 << PSXINT_CDREAD); \
// timing used in this function was taken from tests on real hardware
// (yes it's slow, but you probably don't want to modify it)
-void cdrLidSeekInterrupt()
+void cdrLidSeekInterrupt(void)
{
switch (cdr.DriveState) {
default:
return seekTime;
}
-// also handles seek
-void cdrPlayInterrupt()
+static void cdrReadInterrupt(void);
+
+void cdrPlaySeekReadInterrupt(void)
{
- if (cdr.StatP & STATUS_SEEK) {
+ if (cdr.Reading) {
+ cdrReadInterrupt();
+ return;
+ }
+
+ if (!cdr.Play && (cdr.StatP & STATUS_SEEK)) {
if (cdr.Stat) {
CDR_LOG_I("cdrom: seek stat hack\n");
- CDRSEEKPLAY_INT(0x1000);
+ CDRPLAYSEEKREAD_INT(0x1000, 1);
return;
}
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
- SetPlaySeekRead(cdr.StatP, cdr.Play ? STATUS_PLAY : 0);
+ SetPlaySeekRead(cdr.StatP, 0);
cdr.Result[0] = cdr.StatP;
if (cdr.Irq == 0) {
cdr.Stat = Complete;
Find_CurTrack(cdr.SetSectorPlay);
ReadTrack(cdr.SetSectorPlay);
cdr.TrackChanged = FALSE;
+ return;
}
if (!cdr.Play) return;
CDR_LOG( "CDDA - %d:%d:%d\n",
cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
+ SetPlaySeekRead(cdr.StatP, STATUS_PLAY);
if (memcmp(cdr.SetSectorPlay, cdr.SetSectorEnd, 3) == 0) {
StopCdda();
SetPlaySeekRead(cdr.StatP, 0);
if (!cdr.Irq && !cdr.Stat && (cdr.Mode & (MODE_AUTOPAUSE|MODE_REPORT)))
cdrPlayInterrupt_Autopause();
- if (CDR_readCDDA && !cdr.Muted && !Config.Cdda) {
+ if (!cdr.Muted && !Config.Cdda) {
cdrAttenuate(read_buf, CD_FRAMESIZE_RAW / 4, 1);
- if (SPU_playCDDAchannel)
- SPU_playCDDAchannel(read_buf, CD_FRAMESIZE_RAW);
+ SPU_playCDDAchannel(read_buf, CD_FRAMESIZE_RAW, psxRegs.cycle, cdr.FirstSector);
+ cdr.FirstSector = 0;
}
cdr.SetSectorPlay[2]++;
}
}
- CDRSEEKPLAY_INT(cdReadTime);
+ CDRPLAYSEEKREAD_INT(cdReadTime, 0);
// update for CdlGetlocP/autopause
generate_subq(cdr.SetSectorPlay);
}
-void cdrInterrupt() {
+void cdrInterrupt(void) {
u16 Irq = cdr.Irq;
int no_busy_error = 0;
int start_rotating = 0;
Find_CurTrack(cdr.SetSectorPlay);
ReadTrack(cdr.SetSectorPlay);
cdr.TrackChanged = FALSE;
+ cdr.FirstSector = 1;
if (!Config.Cdda)
CDR_play(cdr.SetSectorPlay);
// BIOS player - set flag again
cdr.Play = TRUE;
- CDRSEEKPLAY_INT(cdReadTime + seekTime);
+ CDRPLAYSEEKREAD_INT(cdReadTime + seekTime, 1);
start_rotating = 1;
break;
Rockman X5 = 0.5-4x
- fix capcom logo
*/
- CDRSEEKPLAY_INT(cdReadTime + seekTime);
+ CDRPLAYSEEKREAD_INT(cdReadTime + seekTime, 1);
start_rotating = 1;
break;
}
cdr.Result[0] |= (cdr.Result[1] >> 4) & 0x08;
- strncpy((char *)&cdr.Result[4], "PCSX", 4);
+ /* This adds the string "PCSX" in Playstation bios boot screen */
+ memcpy((char *)&cdr.Result[4], "PCSX", 4);
cdr.Stat = Complete;
break;
// - fixes new game
ReadTrack(cdr.SetSectorPlay);
-
- // Crusaders of Might and Magic - update getlocl now
- // - fixes cutscene speech
- {
- u8 *buf = CDR_getBuffer();
- 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
- */
-
- /*
- 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.
- */
- CDREAD_INT(((cdr.Mode & 0x80) ? (cdReadTime) : cdReadTime * 2) + seekTime);
+ CDRPLAYSEEKREAD_INT(((cdr.Mode & 0x80) ? (cdReadTime) : cdReadTime * 2) + seekTime, 1);
SetPlaySeekRead(cdr.StatP, STATUS_SEEK);
start_rotating = 1;
}
}
-void cdrReadInterrupt() {
+static void cdrReadInterrupt(void)
+{
u8 *buf;
- if (!cdr.Reading)
- return;
-
if (cdr.Irq || cdr.Stat) {
CDR_LOG_I("cdrom: read stat hack %02x %x\n", cdr.Irq, cdr.Stat);
- CDREAD_INT(2048);
+ CDRPLAYSEEKREAD_INT(2048, 1);
return;
}
memset(cdr.Transfer, 0, DATA_SIZE);
cdr.Stat = DiskError;
cdr.Result[0] |= STATUS_ERROR;
- CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime);
+ setIrq(0x205);
return;
}
int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector);
if (!ret) {
cdrAttenuate(cdr.Xa.pcm, cdr.Xa.nsamples, cdr.Xa.stereo);
- SPU_playADPCMchannel(&cdr.Xa);
+ SPU_playADPCMchannel(&cdr.Xa, psxRegs.cycle, cdr.FirstSector);
cdr.FirstSector = 0;
}
else cdr.FirstSector = -1;
cdr.Readed = 0;
- CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime);
+ CDRPLAYSEEKREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime, 0);
/*
Croc 2: $40 - only FORM1 (*)
DMA_INTERRUPT(3);
}
-void cdrDmaInterrupt()
+void cdrDmaInterrupt(void)
{
if (HW_DMA3_CHCR & SWAP32(0x01000000))
{
Find_CurTrack(cdr.SetSectorPlay);
if (!Config.Cdda)
CDR_play(cdr.SetSectorPlay);
+ if (psxRegs.interrupt & (1 << PSXINT_CDRPLAY_OLD))
+ CDRPLAYSEEKREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime, 1);
}
if ((cdr.freeze_ver & 0xffffff00) != 0x63647200) {
return 0;
}
-void LidInterrupt() {
+void LidInterrupt(void) {
getCdInfo();
cdrLidSeekInterrupt();
}