#include "ppf.h"
#include "psxdma.h"
+/* logging */
+#if 0
+#define CDR_LOG SysPrintf
+#else
+#define CDR_LOG(...)
+#endif
+#if 0
+#define CDR_LOG_I SysPrintf
+#else
+#define CDR_LOG_I(...)
+#endif
+#if 0
+#define CDR_LOG_IO SysPrintf
+#else
+#define CDR_LOG_IO(...)
+#endif
+//#define CDR_LOG_CMD_IRQ
+
cdrStruct cdr;
+static unsigned char *pTransfer;
/* CD-ROM magic numbers */
#define CdlSync 0
// 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;
msf[2] = s;
}
-
+// cdrInterrupt
#define CDR_INT(eCycle) { \
psxRegs.interrupt |= (1 << PSXINT_CDR); \
psxRegs.intCycle[PSXINT_CDR].cycle = eCycle; \
new_dyna_set_event(PSXINT_CDR, eCycle); \
}
+// cdrReadInterrupt
#define CDREAD_INT(eCycle) { \
psxRegs.interrupt |= (1 << PSXINT_CDREAD); \
psxRegs.intCycle[PSXINT_CDREAD].cycle = eCycle; \
new_dyna_set_event(PSXINT_CDREAD, eCycle); \
}
+// cdrLidSeekInterrupt
#define CDRLID_INT(eCycle) { \
psxRegs.interrupt |= (1 << PSXINT_CDRLID); \
psxRegs.intCycle[PSXINT_CDRLID].cycle = eCycle; \
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; \
}
}
-
static void Check_Shell( int Irq )
{
// check case open/close
if (cdr.LidCheck > 0)
{
-#ifdef CDR_LOG
CDR_LOG( "LidCheck\n" );
-#endif
// $20 = check lid state
if( cdr.LidCheck == 0x20 )
if (CDR_getTD((u8)(lcv), cdr.ResultTD) != -1) {
u32 sect1, sect2;
-#ifdef CDR_LOG___0
CDR_LOG( "curtrack %d %d %d | %d %d %d | %d\n",
cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2],
cdr.ResultTD[2], cdr.ResultTD[1], cdr.ResultTD[0],
cdr.CurTrack );
-#endif
// find next track boundary - only need m:s accuracy
sect1 = cdr.SetSectorPlay[0] * 60 * 75 + cdr.SetSectorPlay[1] * 75;
cdr.Prev[1] = itob( time[1] );
cdr.Prev[2] = itob( time[2] );
-#ifdef CDR_LOG
CDR_LOG("ReadTrack() Log: KEY *** %x:%x:%x\n", cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]);
-#endif
cdr.RErr = CDR_readTrack(cdr.Prev);
}
-void AddIrqQueue(unsigned char irq, unsigned long ecycle) {
+static void AddIrqQueue(unsigned char irq, unsigned long ecycle) {
+ if (cdr.Irq != 0 && cdr.Irq != 0xff)
+ CDR_LOG_I("cdr: override cmd %02x -> %02x\n", cdr.Irq, irq);
+
cdr.Irq = irq;
cdr.eCycle = ecycle;
- // Doom: Force rescheduling
- // - Fixes boot
CDR_INT(ecycle);
}
for( lcv = 1; lcv < cdr.ResultTN[1]; lcv++ ) {
if (CDR_getTD((u8)(lcv), cdr.ResultTD) != -1) {
-#ifdef CDR_LOG___0
CDR_LOG( "settrack %d %d %d | %d %d %d | %d\n",
cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2],
cdr.ResultTD[2], cdr.ResultTD[1], cdr.ResultTD[0],
cdr.CurTrack );
-#endif
// check if time matches track start (only need min, sec accuracy)
// - m:s:f vs f:s:m
temp_start[2] = cdr.ResultTD[0];
-#ifdef CDR_LOG
CDR_LOG( "CDDA FAKE SUB - %d:%d:%d / %d:%d:%d / %d:%d:%d\n",
temp_cur[0], temp_cur[1], temp_cur[2],
temp_start[0], temp_start[1], temp_start[2],
temp_next[0], temp_next[1], temp_next[2]);
-#endif
static void cdrPlayInterrupt_Autopause()
{
struct SubQ *subq = (struct SubQ *)CDR_getBufferSub();
+ int track_changed = 0;
if (subq != NULL ) {
-#ifdef CDR_LOG
+ // update subq
+ ReadTrack( cdr.SetSectorPlay );
+
CDR_LOG( "CDDA SUB - %X:%X:%X\n",
subq->AbsoluteAddress[0], subq->AbsoluteAddress[1], subq->AbsoluteAddress[2] );
-#endif
/*
CDDA Autopause
Tomb Raider 1 ($7)
*/
- if( cdr.CurTrack >= btoi( subq->TrackNumber ) )
- return;
+ // .. + 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 {
Create_Fake_Subq();
-#ifdef CDR_LOG___0
CDR_LOG( "CDDA FAKE SUB - %d:%d:%d\n",
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) {
-#ifdef CDR_LOG
+ if ((cdr.Mode & MODE_AUTOPAUSE) && track_changed) {
CDR_LOG( "CDDA STOP\n" );
-#endif
// Magic the Gathering
// - looping territory cdda
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;
-
+ 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;
+
+ cdr.Result[0] = cdr.StatP;
// BIOS CD Player: data already BCD format
cdr.Result[1] = subq->TrackNumber;
cdr.Result[2] = subq->IndexNumber;
cdr.Result[4] = subq->AbsoluteAddress[1];
cdr.Result[5] = subq->AbsoluteAddress[2];
} else {
-#ifdef CDR_LOG___0
CDR_LOG( "REPPLAY FAKE - %d:%d:%d\n",
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);
}
}
+// also handles seek
void cdrPlayInterrupt()
{
- if( !cdr.Play ) return;
+ if (cdr.Seeked == SEEK_DOING_CMD) {
+ if (cdr.Stat) {
+ CDR_LOG_I("cdrom: seek stat hack\n");
+ CDRMISC_INT(0x1000);
+ return;
+ }
+ 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.Reg2 != 0x18)
+ 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();
// Reschedule IRQ
if (cdr.Stat) {
- CDR_INT( 0x100 );
+ CDR_LOG_I("cdrom: stat hack: %02x %x\n", cdr.Irq, cdr.Stat);
+ CDR_INT(0x1000);
return;
}
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;
}
/*
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--;
// GameShark CD Player: Resume play
if( cdr.ParamC == 0 ) {
-#ifdef CDR_LOG___0
CDR_LOG( "PLAY Resume @ %d:%d:%d\n",
cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
-#endif
//CDR_play( cdr.SetSectorPlay );
}
{
// BIOS CD Player: Resume play
if( cdr.Param[0] == 0 ) {
-#ifdef CDR_LOG___0
CDR_LOG( "PLAY Resume T0 @ %d:%d:%d\n",
cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
-#endif
//CDR_play( cdr.SetSectorPlay );
}
else {
-#ifdef CDR_LOG___0
CDR_LOG( "PLAY Resume Td @ %d:%d:%d\n",
cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
-#endif
// BIOS CD Player: Allow track replaying
StopCdda();
cdr.SetSectorPlay[2] = cdr.ResultTD[0];
// reset data
- Set_Track();
+ //Set_Track();
Find_CurTrack();
ReadTrack( cdr.SetSectorPlay );
// BIOS player - set flag again
cdr.Play = TRUE;
- CDRPLAY_INT( cdReadTime );
+ CDRMISC_INT( cdReadTime );
break;
case CdlForward:
subq = (struct SubQ *)CDR_getBufferSub();
if (subq != NULL) {
+ 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;
memcpy(cdr.Result + 2, subq->TrackRelativeAddress, 3);
break;
case CdlSeekL:
+ case CdlSeekP:
SetResultSize(1);
cdr.StatP |= STATUS_ROTATING;
cdr.Result[0] = cdr.StatP;
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:
// - 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) {
- cdr.Seeked = TRUE;
-
+ if (cdr.Seeked != SEEK_DONE) {
cdr.StatP |= STATUS_SEEK;
cdr.StatP &= ~STATUS_READ;
Check_Shell( Irq );
+ cdr.ParamP = 0;
+ cdr.ParamC = 0;
+
if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) {
psxHu32ref(0x1070) |= SWAP32((u32)0x4);
}
-#ifdef CDR_LOG
- CDR_LOG("cdrInterrupt() Log: CDR Interrupt IRQ %x\n", Irq);
+#ifdef CDR_LOG_CMD_IRQ
+ SysPrintf("cdrInterrupt() Log: CDR Interrupt IRQ %d %02x: ",
+ cdr.Stat != NoIntr && cdr.Reg2 != 0x18, Irq);
+ for (i = 0; i < cdr.ResultC; i++)
+ SysPrintf("%02x ", cdr.Result[i]);
+ SysPrintf("\n");
#endif
}
return;
if (cdr.Irq || cdr.Stat) {
- CDREAD_INT(0x100);
+ CDR_LOG_I("cdrom: read stat hack %02x %x\n", cdr.Irq, cdr.Stat);
+ CDREAD_INT(0x1000);
return;
}
-#ifdef CDR_LOG
- CDR_LOG("cdrReadInterrupt() Log: KEY END");
-#endif
-
cdr.OCUP = 1;
SetResultSize(1);
cdr.StatP |= STATUS_READ|STATUS_ROTATING;
cdr.StatP &= ~STATUS_SEEK;
cdr.Result[0] = cdr.StatP;
+ cdr.Seeked = SEEK_DONE;
ReadTrack( cdr.SetSector );
cdr.RErr = -1;
if (cdr.RErr == -1) {
-#ifdef CDR_LOG
- fprintf(emuLog, "cdrReadInterrupt() Log: err\n");
-#endif
+ CDR_LOG_I("cdrReadInterrupt() Log: err\n");
memset(cdr.Transfer, 0, DATA_SIZE);
cdr.Stat = DiskError;
cdr.Result[0] |= STATUS_ERROR;
CheckPPFCache(cdr.Transfer, cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]);
-#ifdef CDR_LOG
- fprintf(emuLog, "cdrReadInterrupt() Log: cdr.Transfer %x:%x:%x\n", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]);
-#endif
+ CDR_LOG("cdrReadInterrupt() Log: cdr.Transfer %x:%x:%x\n", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]);
if ((!cdr.Muted) && (cdr.Mode & MODE_STRSND) && (!Config.Xa) && (cdr.FirstSector != -1)) { // CD-XA
// Firemen 2: Multi-XA files - briefings, cutscenes
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;
}
// G-Police: Don't autopause ADPCM even if mode set (music)
if ((cdr.Transfer[4 + 2] & 0x80) && (cdr.Mode & MODE_AUTOPAUSE) &&
(cdr.Transfer[4 + 2] & 0x4) != 0x4 ) { // EOF
-#ifdef CDR_LOG
+
CDR_LOG("cdrReadInterrupt() Log: Autopausing read\n");
-#endif
+
// AddIrqQueue(AUTOPAUSE, 0x2000);
AddIrqQueue(CdlPause, 0x2000);
}
// What means the 0x10 and the 0x08 bits? I only saw it used by the bios
cdr.Ctrl |= 0x18;
-#ifdef CDR_LOG
- CDR_LOG("cdrRead0() Log: CD0 Read: %x\n", cdr.Ctrl);
-#endif
+ CDR_LOG_IO("cdr r0: %02x\n", cdr.Ctrl);
return psxHu8(0x1800) = cdr.Ctrl;
}
*/
void cdrWrite0(unsigned char rt) {
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite0() Log: CD0 write: %x\n", rt);
-#endif
- cdr.Ctrl = rt | (cdr.Ctrl & ~0x3);
+ CDR_LOG_IO("cdr w0: %02x\n", rt);
- if (rt == 0) {
- cdr.ParamP = 0;
- cdr.ParamC = 0;
- cdr.ResultReady = 0;
- }
+ cdr.Ctrl = (rt & 3) | (cdr.Ctrl & ~3);
}
unsigned char cdrRead1(void) {
} else {
psxHu8(0x1801) = 0;
}
-#ifdef CDR_LOG
- CDR_LOG("cdrRead1() Log: CD1 Read: %x\n", psxHu8(0x1801));
-#endif
+ CDR_LOG_IO("cdr r1: %02x\n", psxHu8(0x1801));
+
return psxHu8(0x1801);
}
void cdrWrite1(unsigned char rt) {
+ u8 set_loc[3];
int i;
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite1() Log: CD1 write: %x (%s)\n", rt, CmdName[rt]);
-#endif
-
+ CDR_LOG_IO("cdr w1: %02x\n", rt);
// Tekken: CDXA fade-out
if( (cdr.Ctrl & 3) == 3 ) {
- //cdr.AttenuatorRight[0] = rt;
+ cdr.AttenuatorRight[0] = rt;
}
cdr.Cmd = rt;
cdr.OCUP = 0;
-#ifdef CDRCMD_DEBUG
+#ifdef CDR_LOG_CMD_IRQ
SysPrintf("cdrWrite1() Log: CD1 write: %x (%s)", rt, CmdName[rt]);
if (cdr.ParamC) {
SysPrintf(" Param[%d] = {", cdr.ParamC);
}
#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]);
- cdr.SetSector[3] = 0;
+ set_loc[i] = btoi(cdr.Param[i]);
- /*
- if ((cdr.SetSector[0] | cdr.SetSector[1] | cdr.SetSector[2]) == 0) {
- *(u32 *)cdr.SetSector = *(u32 *)cdr.SetSectorSeek;
- }*/
+ i = abs(msf2sec(cdr.SetSector) - msf2sec(set_loc));
+ if (i > 16)
+ cdr.Seeked = SEEK_PENDING;
+
+ memcpy(cdr.SetSector, set_loc, 3);
+ cdr.SetSector[3] = 0;
cdr.Ctrl |= 0x80;
cdr.Stat = NoIntr;
case CdlReset:
case CdlInit:
+ cdr.Seeked = SEEK_DONE;
StopCdda();
StopReading();
cdr.Ctrl |= 0x80;
break;
case CdlSetmode:
-#ifdef CDR_LOG
CDR_LOG("cdrWrite1() Log: Setmode %x\n", cdr.Param[0]);
-#endif
+
cdr.Mode = cdr.Param[0];
cdr.Ctrl |= 0x80;
cdr.Stat = NoIntr;
break;
default:
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite1() Log: Unknown command: %x\n", cdr.Cmd);
-#endif
+ cdr.ParamP = 0;
+ cdr.ParamC = 0;
+ CDR_LOG_I("cdrWrite1() Log: Unknown command: %x\n", cdr.Cmd);
return;
}
if (cdr.Stat != NoIntr) {
if (cdr.Readed == 0) {
ret = 0;
} else {
- ret = *cdr.pTransfer++;
+ ret = *pTransfer++;
}
-#ifdef CDR_LOG
- CDR_LOG("cdrRead2() Log: CD2 Read: %x\n", ret);
-#endif
+ CDR_LOG_IO("cdr r2: %02x\n", ret);
return ret;
}
void cdrWrite2(unsigned char rt) {
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite2() Log: CD2 write: %x\n", rt);
-#endif
+ CDR_LOG_IO("cdr w2: %02x\n", rt);
// 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++;
}
} else {
psxHu8(0x1803) = 0;
}
-#ifdef CDR_LOG
- CDR_LOG("cdrRead3() Log: CD3 Read: %x\n", psxHu8(0x1803));
-#endif
+
+ CDR_LOG_IO("cdr r3: %02x\n", psxHu8(0x1803));
return psxHu8(0x1803);
}
void cdrWrite3(unsigned char rt) {
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite3() Log: CD3 write: %x\n", rt);
-#endif
-/*
+ CDR_LOG_IO("cdr w3: %02x\n", rt);
+
// Tekken: CDXA fade-out
if( (cdr.Ctrl & 3) == 2 ) {
cdr.AttenuatorLeft[1] = rt;
}
else if( (cdr.Ctrl & 3) == 3 && rt == 0x20 ) {
-#ifdef CDR_LOG
CDR_LOG( "CD-XA Volume: %X %X | %X %X\n",
cdr.AttenuatorLeft[0], cdr.AttenuatorLeft[1],
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
+ CDR_LOG_I("-- 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;
+ pTransfer = cdr.Transfer;
switch (cdr.Mode & 0x30) {
case MODE_SIZE_2328:
case 0x00:
- cdr.pTransfer += 12;
+ pTransfer += 12;
break;
case MODE_SIZE_2340:
- cdr.pTransfer += 0;
+ pTransfer += 0;
break;
default:
void psxDma3(u32 madr, u32 bcr, u32 chcr) {
u32 cdsize;
+ int size;
u8 *ptr;
-#ifdef CDR_LOG
CDR_LOG("psxDma3() Log: *** DMA 3 *** %x addr = %x size = %x\n", chcr, madr, bcr);
-#endif
switch (chcr) {
case 0x11000000:
case 0x11400100:
if (cdr.Readed == 0) {
-#ifdef CDR_LOG
CDR_LOG("psxDma3() Log: *** DMA 3 *** NOT READY\n");
-#endif
break;
}
ptr = (u8 *)PSXM(madr);
if (ptr == NULL) {
-#ifdef CPU_LOG
CDR_LOG("psxDma3() Log: *** DMA 3 *** NULL Pointer!\n");
-#endif
break;
}
- 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 - (pTransfer - cdr.Transfer);
+ if (size > cdsize)
+ size = cdsize;
+ if (size > 0)
{
- memcpy(ptr, cdr.pTransfer, cdsize);
+ memcpy(ptr, pTransfer, size);
}
psxCpu->Clear(madr, cdsize / 4);
- cdr.pTransfer += cdsize;
+ pTransfer += cdsize;
// burst vs normal
return;
default:
-#ifdef CDR_LOG
CDR_LOG("psxDma3() Log: Unknown cddma %x\n", chcr);
-#endif
break;
}
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;
-}
+ pTransfer = cdr.Transfer;
-int cdrFreeze(gzFile f, int Mode) {
- uintptr_t tmp;
+ // BIOS player - default values
+ cdr.AttenuatorLeft[0] = 0x80;
+ cdr.AttenuatorLeft[1] = 0x00;
+ cdr.AttenuatorRight[0] = 0x80;
+ cdr.AttenuatorRight[1] = 0x00;
+}
+int cdrFreeze(void *f, int Mode) {
+ u32 tmp;
if( Mode == 0 ) {
StopCdda();
gzfreeze(&cdr, sizeof(cdr));
if (Mode == 1)
- tmp = cdr.pTransfer - cdr.Transfer;
+ tmp = pTransfer - cdr.Transfer;
gzfreeze(&tmp, sizeof(tmp));
- if (Mode == 0)
- cdr.pTransfer = cdr.Transfer + tmp;
+ if (Mode == 0) {
+ pTransfer = cdr.Transfer + tmp;
+
+ if (cdr.Play && !Config.Cdda)
+ CDR_play(cdr.SetSectorPlay);
+ }
return 0;
}