static void cdrPlayInterrupt_Autopause()
{
struct SubQ *subq = (struct SubQ *)CDR_getBufferSub();
+ int track_changed = 0;
if (subq != NULL ) {
#ifdef CDR_LOG
CDR_LOG( "CDDA SUB - %X:%X:%X\n",
Tomb Raider 1 ($7)
*/
- if( cdr.CurTrack >= btoi( subq->TrackNumber ) )
- return;
+ if( cdr.CurTrack < btoi( subq->TrackNumber ) )
+ track_changed = 1;
} else {
Create_Fake_Subq();
#ifdef CDR_LOG___0
fake_subq_real[0], fake_subq_real[1], fake_subq_real[2] );
#endif
- if( !fake_subq_change )
- return;
-
+ track_changed = fake_subq_change;
fake_subq_change = 0;
}
- if (cdr.Mode & MODE_AUTOPAUSE) {
+ if ((cdr.Mode & MODE_AUTOPAUSE) && track_changed) {
#ifdef CDR_LOG
CDR_LOG( "CDDA STOP\n" );
#endif
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",
#endif
cdr.CurTrack = btoi( subq->TrackNumber );
+ if (subq->AbsoluteAddress[2] & 0xf)
+ return;
+
+ cdr.Result[0] = cdr.StatP;
// BIOS CD Player: data already BCD format
cdr.Result[1] = subq->TrackNumber;
cdr.Result[2] = subq->IndexNumber;
fake_subq_real[0], fake_subq_real[1], fake_subq_real[2] );
#endif
+ if (fake_subq_real[2] & 0xf)
+ return;
+
+ cdr.Result[0] = cdr.StatP;
// track # / index #
cdr.Result[1] = itob(cdr.CurTrack);
cdr.Result[2] = itob(fake_subq_index);
Wild 9: skip PREGAP + starting accurate SubQ
- plays tracks without retry play
*/
+ /* unneeded with correct cdriso?
Set_Track();
+ */
Find_CurTrack();
ReadTrack( cdr.SetSectorPlay );
-
// GameShark CD Player: Calls 2x + Play 2x
if( cdr.FastBackward || cdr.FastForward ) {
if( cdr.FastForward ) cdr.FastForward--;
// - fixes cutscene speech
{
u8 *buf = CDR_getBuffer();
- memcpy(cdr.Transfer, buf, 8);
+ 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) {
Check_Shell( Irq );
+ cdr.ParamP = 0;
+ cdr.ParamC = 0;
+
if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) {
psxHu32ref(0x1070) |= SWAP32((u32)0x4);
}
int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector);
if (!ret) {
+ // only handle attenuator basic channel switch for now
+ if (cdr.Xa.stereo) {
+ int i;
+ if ((cdr.AttenuatorLeft[0] | cdr.AttenuatorLeft[1])
+ && !(cdr.AttenuatorRight[0] | cdr.AttenuatorRight[1]))
+ {
+ for (i = 0; i < cdr.Xa.nsamples; i++)
+ cdr.Xa.pcm[i*2 + 1] = cdr.Xa.pcm[i*2];
+ }
+ else if (!(cdr.AttenuatorLeft[0] | cdr.AttenuatorLeft[1])
+ && (cdr.AttenuatorRight[0] | cdr.AttenuatorRight[1]))
+ {
+ for (i = 0; i < cdr.Xa.nsamples; i++)
+ cdr.Xa.pcm[i*2] = cdr.Xa.pcm[i*2 + 1];
+ }
+ }
+
SPU_playADPCMchannel(&cdr.Xa);
cdr.FirstSector = 0;
-
+#if 0
// Crash Team Racing: music, speech
+ // - done using cdda decoded buffer (spu irq)
+ // - don't do here
// signal ADPCM data ready
psxHu32ref(0x1070) |= SWAP32((u32)0x200);
+#endif
}
else cdr.FirstSector = -1;
}
#ifdef CDR_LOG
CDR_LOG("cdrWrite0() Log: CD0 write: %x\n", rt);
#endif
- cdr.Ctrl = rt | (cdr.Ctrl & ~0x3);
-
- if (rt == 0) {
- cdr.ParamP = 0;
- cdr.ParamC = 0;
- cdr.ResultReady = 0;
- }
+ cdr.Ctrl = (rt & 3) | (cdr.Ctrl & ~3);
}
unsigned char cdrRead1(void) {
}
void cdrWrite1(unsigned char rt) {
+ char set_loc[3];
int i;
#ifdef CDR_LOG
// Tekken: CDXA fade-out
if( (cdr.Ctrl & 3) == 3 ) {
- //cdr.AttenuatorRight[0] = rt;
+ cdr.AttenuatorRight[0] = rt;
}
}
#endif
- if (cdr.Ctrl & 0x1) return;
+ if (cdr.Ctrl & 0x3) return;
+
+ cdr.ResultReady = 0;
switch (cdr.Cmd) {
case CdlSync:
case CdlSetloc:
StopReading();
- cdr.Seeked = FALSE;
for (i = 0; i < 3; i++)
- cdr.SetSector[i] = btoi(cdr.Param[i]);
+ set_loc[i] = btoi(cdr.Param[i]);
+ i = abs(msf2sec(cdr.SetSector) - msf2sec(set_loc));
+ if (i > 16)
+ cdr.Seeked = FALSE;
+ memcpy(cdr.SetSector, set_loc, 3);
cdr.SetSector[3] = 0;
/*
break;
default:
+ cdr.ParamP = 0;
+ cdr.ParamC = 0;
#ifdef CDR_LOG
CDR_LOG("cdrWrite1() Log: Unknown command: %x\n", cdr.Cmd);
#endif
// Tekken: CDXA fade-out
if( (cdr.Ctrl & 3) == 2 ) {
- //cdr.AttenuatorLeft[0] = rt;
+ cdr.AttenuatorLeft[0] = rt;
}
else if( (cdr.Ctrl & 3) == 3 ) {
- //cdr.AttenuatorRight[1] = rt;
+ cdr.AttenuatorRight[1] = rt;
}
cdr.Reg2 = rt;
break;
}
- } else if (!(cdr.Ctrl & 0x1) && cdr.ParamP < 8) {
+ } else if (!(cdr.Ctrl & 0x3) && cdr.ParamP < 8) {
cdr.Param[cdr.ParamP++] = rt;
cdr.ParamC++;
}
#ifdef CDR_LOG
CDR_LOG("cdrWrite3() Log: CD3 write: %x\n", rt);
#endif
-/*
+
// Tekken: CDXA fade-out
if( (cdr.Ctrl & 3) == 2 ) {
cdr.AttenuatorLeft[1] = rt;
cdr.AttenuatorRight[0], cdr.AttenuatorRight[1] );
#endif
}
-*/
+
// GameShark CDX CD Player: Irq timing mania
if( rt == 0 &&
}
- if (rt == 0x07 && cdr.Ctrl & 0x1) {
+ if (rt == 0x07 && (cdr.Ctrl & 3) == 1) {
cdr.Stat = 0;
if (cdr.Irq == 0xff) {
// - Final Fantasy Tactics
// - various other games
- if (cdr.Irq) // rearmed guesswork hack
if (cdr.Reading && !cdr.ResultReady) {
- CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime);
+ int left = psxRegs.intCycle[PSXINT_CDREAD].sCycle + psxRegs.intCycle[PSXINT_CDREAD].cycle - psxRegs.cycle;
+ int time = (cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime;
+ if (Config.CdrReschedule != 2)
+ if (left < time / 2 || Config.CdrReschedule) { // rearmed guesswork hack
+ //printf("-- resched %d -> %d\n", left, time);
+ CDREAD_INT(time);
+ }
}
return;
}
- if (rt == 0x80 && !(cdr.Ctrl & 0x1) && cdr.Readed == 0) {
+ if (rt == 0x80 && !(cdr.Ctrl & 0x3) && cdr.Readed == 0) {
cdr.Readed = 1;
cdr.pTransfer = cdr.Transfer;
void psxDma3(u32 madr, u32 bcr, u32 chcr) {
u32 cdsize;
+ int size;
u8 *ptr;
#ifdef CDR_LOG
- CdlPlay
- Spams DMA3 and gets buffer overrun
*/
-
- if( (cdr.pTransfer-cdr.Transfer) + cdsize > 2352 )
- {
- // avoid crash - probably should wrap here
- //memcpy(ptr, cdr.pTransfer, cdsize);
- }
- else
+ size = CD_FRAMESIZE_RAW - (cdr.pTransfer - cdr.Transfer);
+ if (size > cdsize)
+ size = cdsize;
+ if (size > 0)
{
- memcpy(ptr, cdr.pTransfer, cdsize);
+ memcpy(ptr, cdr.pTransfer, size);
}
psxCpu->Clear(madr, cdsize / 4);
void cdrDmaInterrupt()
{
- HW_DMA3_CHCR &= SWAP32(~0x01000000);
- DMA_INTERRUPT(3);
+ if (HW_DMA3_CHCR & SWAP32(0x01000000))
+ {
+ HW_DMA3_CHCR &= SWAP32(~0x01000000);
+ DMA_INTERRUPT(3);
+ }
}
void cdrReset() {
cdr.CurTrack = 1;
cdr.File = 1;
cdr.Channel = 1;
+
+ // BIOS player - default values
+ cdr.AttenuatorLeft[0] = 0x80;
+ cdr.AttenuatorLeft[1] = 0x00;
+ cdr.AttenuatorRight[0] = 0x80;
+ cdr.AttenuatorRight[1] = 0x00;
}
int cdrFreeze(gzFile f, int Mode) {
gzfreeze(&tmp, sizeof(tmp));
- if (Mode == 0)
+ if (Mode == 0) {
cdr.pTransfer = cdr.Transfer + tmp;
+ if (cdr.Play && !Config.Cdda)
+ CDR_play(cdr.SetSectorPlay);
+ }
+
return 0;
}