#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;
#define CdlReset 28
#define CdlReadToc 30
-#define AUTOPAUSE 249
-#define READ_ACK 250
-#define READ 251
-#define REPPLAY_ACK 252
-#define REPPLAY 253
-#define ASYNC 254
-/* don't set 255, it's reserved */
-
char *CmdName[0x100]= {
"CdlSync", "CdlNop", "CdlSetloc", "CdlPlay",
"CdlForward", "CdlBackward", "CdlReadN", "CdlStandby",
new_dyna_set_event(PSXINT_CDRPLAY, eCycle); \
}
-#define StartReading(type, eCycle) { \
- cdr.Reading = type; \
- cdr.FirstSector = 1; \
- cdr.Readed = 0xff; \
- AddIrqQueue(READ_ACK, eCycle); \
-}
-
#define StopReading() { \
if (cdr.Reading) { \
cdr.Reading = 0; \
}
#define SetResultSize(size) { \
- cdr.ResultP = 0; \
+ cdr.ResultP = 0; \
cdr.ResultC = size; \
cdr.ResultReady = 1; \
}
+static void setIrq(void)
+{
+ if (cdr.Stat & cdr.Reg2)
+ psxHu32ref(0x1070) |= SWAP32((u32)0x4);
+}
void cdrLidSeekInterrupt()
{
// 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.Stat == NoIntr )
cdr.Stat = Acknowledge;
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
-
+ setIrq();
// begin close-seek-ready cycle
CDRLID_INT( cdReadTime * 3 );
if( cdr.Stat == NoIntr )
cdr.Stat = Acknowledge;
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
+ setIrq();
}
}
}
-
void Find_CurTrack() {
cdr.CurTrack = 0;
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);
}
static void AddIrqQueue(unsigned char irq, unsigned long ecycle) {
- //if (cdr.Irq != 0 && cdr.Irq != 0xff)
- // printf("cdr: override cmd %02x -> %02x\n", cdr.Irq, irq);
+ if (cdr.Irq != 0)
+ CDR_LOG_I("cdr: override cmd %02x -> %02x\n", cdr.Irq, irq);
cdr.Irq = irq;
cdr.eCycle = 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
// update subq
ReadTrack( cdr.SetSectorPlay );
-#ifdef CDR_LOG
CDR_LOG( "CDDA SUB - %X:%X:%X\n",
subq->AbsoluteAddress[0], subq->AbsoluteAddress[1], subq->AbsoluteAddress[2] );
-#endif
/*
CDDA Autopause
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
track_changed = fake_subq_change;
fake_subq_change = 0;
}
if ((cdr.Mode & MODE_AUTOPAUSE) && track_changed) {
-#ifdef CDR_LOG
CDR_LOG( "CDDA STOP\n" );
-#endif
// Magic the Gathering
// - looping territory cdda
//cdr.ResultReady = 1;
//cdr.Stat = DataReady;
cdr.Stat = DataEnd;
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
+ setIrq();
StopCdda();
}
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
+
// breaks when .sub doesn't have index 0 for some reason (bad rip?)
//cdr.CurTrack = btoi( subq->TrackNumber );
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.Stat = DataReady;
SetResultSize(8);
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
+ setIrq();
}
}
void cdrPlayInterrupt()
{
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) {
+ if (cdr.Irq == 0) {
cdr.Stat = Complete;
- if (cdr.Reg2 != 0x18)
- psxHu32ref(0x1070) |= SWAP32(0x4);
+ setIrq();
}
cdr.Seeked = SEEK_PENDING;
if (!cdr.Play) return;
-#ifdef CDR_LOG
CDR_LOG( "CDDA - %d:%d:%d\n",
cdr.SetSectorPlay[0], cdr.SetSectorPlay[1], cdr.SetSectorPlay[2] );
-#endif
+
CDRMISC_INT( cdReadTime );
if (!cdr.Irq && !cdr.Stat && (cdr.Mode & MODE_CDDA) && (cdr.Mode & (MODE_AUTOPAUSE|MODE_REPORT)))
// 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;
}
- cdr.Irq = 0xff;
+ cdr.Irq = 0;
cdr.Ctrl &= ~0x80;
switch (Irq) {
// 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.Stat = Complete;
break;
- case AUTOPAUSE:
- cdr.OCUP = 0;
-/* SetResultSize(1);
- StopCdda();
- StopReading();
- cdr.OCUP = 0;
- cdr.StatP&=~0x20;
- cdr.StatP|= 0x2;
- cdr.Result[0] = cdr.StatP;
- cdr.Stat = DataEnd;
-*/ AddIrqQueue(CdlPause, 0x800);
- break;
-
- case READ_ACK:
+ case CdlReadN:
+ case CdlReadS:
if (!cdr.Reading) return;
Check_Shell( Irq );
- cdr.ParamP = 0;
cdr.ParamC = 0;
- if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) {
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
- }
+ setIrq();
-#ifdef CDR_LOG
- printf("cdrInterrupt() Log: CDR Interrupt IRQ %x: ", 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++)
- printf("%02x ", cdr.Result[i]);
- printf("\n");
+ 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.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
// - don't do here
// signal ADPCM data ready
- psxHu32ref(0x1070) |= SWAP32((u32)0x200);
+ setIrq();
#endif
}
else cdr.FirstSector = -1;
cdr.Readed = 0;
- // 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);
- }
- else {
- CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime);
- }
+ CDREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime);
/*
Croc 2: $40 - only FORM1 (*)
Sim Theme Park - no adpcm at all (zero)
*/
- if( (cdr.Mode & MODE_STRSND) == 0 || (cdr.Transfer[4+2] & 0x4) != 0x4 ) {
+ if (!(cdr.Mode & MODE_STRSND) || !(cdr.Transfer[4+2] & 0x4)) {
cdr.Stat = DataReady;
- } else {
- // Breath of Fire 3 - fix inn sleeping
- // Rockman X5 - no music restart problem
- cdr.Stat = NoIntr;
+ setIrq();
}
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
Check_Shell(0);
}
/*
cdrRead0:
- bit 0 - 0 REG1 command send / 1 REG1 data read
- bit 1 - 0 data transfer finish / 1 data transfer ready/in progress
+ bit 0,1 - mode
bit 2 - unknown
bit 3 - unknown
bit 4 - unknown
// 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;
}
-/*
-cdrWrite0:
- 0 - to send a command / 1 - to get the result
-*/
-
void cdrWrite0(unsigned char rt) {
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite0() Log: CD0 write: %x\n", rt);
-#endif
+ CDR_LOG_IO("cdr w0: %02x\n", rt);
+
cdr.Ctrl = (rt & 3) | (cdr.Ctrl & ~3);
}
unsigned char cdrRead1(void) {
- if (cdr.ResultReady) { // && cdr.Ctrl & 0x1) {
- // GameShark CDX CD Player: uses 17 bytes output (wraps around)
+ if ((cdr.ResultP & 0xf) < cdr.ResultC)
psxHu8(0x1801) = cdr.Result[cdr.ResultP & 0xf];
- cdr.ResultP++;
- if (cdr.ResultP == cdr.ResultC)
- cdr.ResultReady = 0;
- } else {
+ else
psxHu8(0x1801) = 0;
- }
-#ifdef CDR_LOG
- CDR_LOG("cdrRead1() Log: CD1 Read: %x\n", psxHu8(0x1801));
-#endif
+ cdr.ResultP++;
+ if (cdr.ResultP == cdr.ResultC)
+ cdr.ResultReady = 0;
+
+ CDR_LOG_IO("cdr r1: %02x\n", psxHu8(0x1801));
+
return psxHu8(0x1801);
}
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;
+ switch (cdr.Ctrl & 3) {
+ case 0:
+ break;
+ case 3:
+ cdr.AttenuatorRight[1] = rt;
+ return;
+ default:
+ return;
}
-
-// psxHu8(0x1801) = 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 & 0x3) return;
-
cdr.ResultReady = 0;
+ cdr.Ctrl |= 0x80;
+ // cdr.Stat = NoIntr;
+ AddIrqQueue(cdr.Cmd, 0x800);
switch (cdr.Cmd) {
- case CdlSync:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlNop:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
-
- // Twisted Metal 3 - fix music
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
+ case CdlSync:
+ case CdlNop:
+ case CdlForward:
+ case CdlBackward:
+ case CdlReadT:
+ case CdlTest:
+ case CdlID:
+ case CdlReadToc:
+ case CdlGetmode:
+ case CdlGetlocL:
+ case CdlGetlocP:
+ case CdlGetTD:
+ break;
- case CdlSetloc:
+ case CdlSetloc:
StopReading();
for (i = 0; i < 3; i++)
set_loc[i] = btoi(cdr.Param[i]);
i = abs(msf2sec(cdr.SetSector) - msf2sec(set_loc));
if (i > 16)
- cdr.Seeked = SEEK_PENDING;
+ cdr.Seeked = SEEK_PENDING;
memcpy(cdr.SetSector, set_loc, 3);
- cdr.SetSector[3] = 0;
-
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
+ cdr.SetSector[3] = 0;
+ break;
- case CdlPlay:
+ case CdlPlay:
// Vib Ribbon: try same track again
StopCdda();
//TODO?
//CDRDBUF_INT( PSXCLK / 44100 * 0x100 );
-
cdr.Play = TRUE;
cdr.StatP |= STATUS_SEEK;
cdr.StatP &= ~STATUS_ROTATING;
+ break;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlForward:
- //if (cdr.CurTrack < 0xaa)
- // cdr.CurTrack++;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlBackward:
- //if (cdr.CurTrack > 1)
- //cdr.CurTrack--;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlReadN:
- cdr.Irq = 0;
+ case CdlReadN:
StopReading();
- cdr.Ctrl|= 0x80;
- cdr.Stat = NoIntr;
- StartReading(1, 0x800);
+ cdr.Reading = 1;
+ cdr.FirstSector = 1;
+ cdr.Readed = 0xff;
break;
- case CdlStandby:
+ case CdlStandby:
StopCdda();
StopReading();
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
+ break;
- case CdlStop:
+ case CdlStop:
// GameShark CD Player: Reset CDDA to track start
if( cdr.Play && CDR_getStatus(&stat) != -1 ) {
cdr.SetSectorPlay[0] = stat.Time[0];
Find_CurTrack();
-
// grab time for current track
CDR_getTD((u8)(cdr.CurTrack), cdr.ResultTD);
StopCdda();
StopReading();
+ break;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlPause:
+ case CdlPause:
/*
GameShark CD Player: save time for resume
StopCdda();
StopReading();
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
-
- AddIrqQueue(cdr.Cmd, 0x800);
break;
case CdlReset:
- case CdlInit:
+ case CdlInit:
cdr.Seeked = SEEK_DONE;
StopCdda();
StopReading();
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlMute:
- cdr.Muted = TRUE;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
+ break;
+ case CdlMute:
+ cdr.Muted = TRUE;
// Duke Nukem - Time to Kill
// - do not directly set cd-xa volume
//SPU_writeRegister( H_CDLeft, 0x0000 );
//SPU_writeRegister( H_CDRight, 0x0000 );
- break;
+ break;
- case CdlDemute:
- cdr.Muted = FALSE;
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
+ case CdlDemute:
+ cdr.Muted = FALSE;
// Duke Nukem - Time to Kill
// - do not directly set cd-xa volume
//SPU_writeRegister( H_CDLeft, 0x7f00 );
//SPU_writeRegister( H_CDRight, 0x7f00 );
- break;
+ break;
case CdlSetfilter:
cdr.File = cdr.Param[0];
cdr.Channel = cdr.Param[1];
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
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;
- AddIrqQueue(cdr.Cmd, 0x800);
// Squaresoft on PlayStation 1998 Collector's CD Vol. 1
// - fixes choppy movie sound
StopCdda();
break;
- case CdlGetmode:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlGetlocL:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
-
- // Crusaders of Might and Magic - cutscene speech
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlGetlocP:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
-
- // GameShark CDX / Lite Player: pretty narrow time window
- // - doesn't always work due to time inprecision
- //AddIrqQueue(cdr.Cmd, 0x28);
-
- // Tomb Raider 2 - cdda
- //AddIrqQueue(cdr.Cmd, 0x40);
-
- // rearmed: the above works in pcsxr-svn, but breaks here
- // (TOCA world touring cars), perhaps some other code is not merged yet
- AddIrqQueue(cdr.Cmd, 0x1000);
- break;
-
case CdlGetTN:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
//AddIrqQueue(cdr.Cmd, 0x800);
// GameShark CDX CD Player: very long time
AddIrqQueue(cdr.Cmd, 0x100000);
break;
- case CdlGetTD:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
case CdlSeekL:
-// ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0];
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
-
- StopCdda();
- StopReading();
-
- break;
-
case CdlSeekP:
-// ((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0];
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
-
// Tomb Raider 2 - reset cdda
StopCdda();
StopReading();
-
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- // Destruction Derby: read TOC? GetTD after this
- case CdlReadT:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
break;
- case CdlTest:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- case CdlID:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
case CdlReadS:
- cdr.Irq = 0;
StopReading();
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- StartReading(2, 0x800);
+ cdr.Reading = 2;
+ cdr.FirstSector = 1;
+ cdr.Readed = 0xff;
break;
- case CdlReadToc:
- cdr.Ctrl |= 0x80;
- cdr.Stat = NoIntr;
- AddIrqQueue(cdr.Cmd, 0x800);
- break;
-
- default:
- cdr.ParamP = 0;
+ default:
cdr.ParamC = 0;
-#ifdef CDR_LOG
- CDR_LOG("cdrWrite1() Log: Unknown command: %x\n", cdr.Cmd);
-#endif
+ CDR_LOG_I("cdrWrite1() Log: Unknown command: %x\n", cdr.Cmd);
return;
}
- if (cdr.Stat != NoIntr) {
- psxHu32ref(0x1070) |= SWAP32((u32)0x4);
- }
}
unsigned char cdrRead2(void) {
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 ) {
+ switch (cdr.Ctrl & 3) {
+ case 0:
+ if (cdr.ParamC < 8) // FIXME: size and wrapping
+ cdr.Param[cdr.ParamC++] = rt;
+ return;
+ case 1:
+ cdr.Reg2 = rt;
+ setIrq();
+ return;
+ case 2:
cdr.AttenuatorLeft[0] = rt;
- }
- else if( (cdr.Ctrl & 3) == 3 ) {
- cdr.AttenuatorRight[1] = rt;
- }
-
-
- if (cdr.Ctrl & 0x1) {
- switch (rt) {
- case 0x07:
- cdr.ParamP = 0;
- cdr.ParamC = 0;
- cdr.ResultReady = 1; //0;
- cdr.Ctrl &= ~3; //cdr.Ctrl = 0;
- break;
-
- default:
- cdr.Reg2 = rt;
- break;
- }
- } else if (!(cdr.Ctrl & 0x3) && cdr.ParamP < 8) {
- cdr.Param[cdr.ParamP++] = rt;
- cdr.ParamC++;
+ return;
+ case 3:
+ cdr.AttenuatorRight[0] = rt;
+ return;
}
}
unsigned char cdrRead3(void) {
- if (cdr.Stat) {
- if (cdr.Ctrl & 0x1)
- psxHu8(0x1803) = cdr.Stat | 0xE0;
- else
- psxHu8(0x1803) = 0xff;
- } else {
- psxHu8(0x1803) = 0;
- }
-#ifdef CDR_LOG
- CDR_LOG("cdrRead3() Log: CD3 Read: %x\n", psxHu8(0x1803));
-#endif
+ if (cdr.Ctrl & 0x1)
+ psxHu8(0x1803) = cdr.Stat | 0xE0;
+ else
+ psxHu8(0x1803) = cdr.Reg2 | 0xE0;
+
+ 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);
+
+ switch (cdr.Ctrl & 3) {
+ case 0:
+ break; // transfer
+ case 1:
+ cdr.Stat &= ~rt;
- // Tekken: CDXA fade-out
- if( (cdr.Ctrl & 3) == 2 ) {
+ if (rt & 0x40)
+ cdr.ParamC = 0;
+ return;
+ case 2:
cdr.AttenuatorLeft[1] = rt;
- }
- else if( (cdr.Ctrl & 3) == 3 && rt == 0x20 ) {
-#ifdef CDR_LOG
+ return;
+ case 3:
+ if (rt == 0x20)
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 &&
- cdr.Irq != 0 && cdr.Irq != 0xff &&
- cdr.ResultReady == 0 ) {
-
- // GS CDX: ~0x28 cycle timing - way too precise
- if( cdr.Irq == CdlGetlocP ) {
- cdrInterrupt();
-
- psxRegs.interrupt &= ~(1 << PSXINT_CDR);
- }
- }
-
-
- if (rt == 0x07 && (cdr.Ctrl & 3) == 1) {
- cdr.Stat = 0;
-
- if (cdr.Irq == 0xff) {
- cdr.Irq = 0;
- return;
- }
-
- // XA streaming - incorrect timing because of this reschedule
- // - Final Fantasy Tactics
- // - various other games
-
- if (cdr.Reading && !cdr.ResultReady) {
- 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 & 0x3) && cdr.Readed == 0) {
+ if ((rt & 0x80) && cdr.Readed == 0) {
cdr.Readed = 1;
pTransfer = cdr.Transfer;
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;
}
return;
default:
-#ifdef CDR_LOG
CDR_LOG("psxDma3() Log: Unknown cddma %x\n", chcr);
-#endif
break;
}
// BIOS player - default values
cdr.AttenuatorLeft[0] = 0x80;
cdr.AttenuatorLeft[1] = 0x00;
- cdr.AttenuatorRight[0] = 0x80;
- cdr.AttenuatorRight[1] = 0x00;
+ cdr.AttenuatorRight[0] = 0x00;
+ cdr.AttenuatorRight[1] = 0x80;
}
int cdrFreeze(void *f, int Mode) {
gzfreeze(&cdr, sizeof(cdr));
- if (Mode == 1)
+ if (Mode == 1) {
+ cdr.ParamP = cdr.ParamC;
tmp = pTransfer - cdr.Transfer;
+ }
gzfreeze(&tmp, sizeof(tmp));
cdr.LidCheck = 0x20; // start checker
CDRLID_INT( cdReadTime * 3 );
-
+
// generate interrupt if none active - open or close
if (cdr.Irq == 0 || cdr.Irq == 0xff) {
cdr.Ctrl |= 0x80;